无法获取OkHttp的response.body.toString()返回字符串


77

我正在尝试使用OkHttp获取一些json数据,并且无法弄清楚为什么当我尝试记录response.body().toString()所得到的是Results:﹕ com.squareup.okhttp.Call$RealResponseBody@41c16aa8

try {
        URL url = new URL(BaseUrl);
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .header(/****/)
                .build();

        Call call = client.newCall(request);
        Response response = call.execute();

        **//for some reason this successfully prints out the response**
        System.out.println("YEAH: " + response.body().string());

        if(!response.isSuccessful()) {
            Log.i("Response code", " " + response.code());
        }

        Log.i("Response code", response.code() + " ");
        String results = response.body().toString();

        Log.i("OkHTTP Results: ", results);

记录

我不知道我在做什么错。我如何获得响应字符串?



您只需打印一个对象,然后跟踪即可确认它。
米歇尔·达米科

3
阅读文档。您正在寻找的方法是string
njzk2

val responseBodyString = response.body()!!。string()response = response.newBuilder().body(ResponseBody.create(responseBody?.contentType(),responseBodyString.toByteArray())).build()
Imran Baig

Answers:


33

以防万一有人碰到和我一样奇怪的事情。我在调试模式下(显然是从OKHttp 2.4开始)在开发过程中运行代码

..响应主体是一次性值,只能使用一次

因此,在调试时,检查员会调用“幕后”,并且主体始终为空。参见:https : //square.github.io/okhttp/3.x/okhttp/okhttp3/ResponseBody.html


3
.string()不消耗响应主体的情况下如何打电话?
osrl 2015年

1
不知道是否可以在不占用响应主体的情况下调用.string(),但可以解决此问题,但是您可以遵循okhttp的日志记录拦截器用来执行此操作的模式:github.com/square/okhttp/blob/master/okhttp-测井拦截器/…
liampronan

1
这意味着我们无法调试Okhttp响应正文

1
您可以将响应正文打印到禁用调试的日志
Oded Regev

3
多么邪恶的行为!我知道这种评论是无助的,不过还是要谢谢您
Sergei Voitovich

236

您可以使用.string()函数在中打印响应System.out.println()。但是最后Log.i()你正在使用.toString()

因此,请.string()在响应正文上使用以打印并获取您请求的响应,例如:

response.body().string();

注意:

  1. .toString():这将以字符串格式返回对象。

  2. .string():这将返回您的回复。

我认为这可以解决您的问题。


2
没有更多的string()函数,现在怎么办?
eC Droid

@eCDroid“没有更多的string()函数”确定吗?
s18

1
根据文档`自动关闭ResponseBody。`您需要记住,调用此方法后将无法读取响应
Roman Nazarevych


1

以下是我修改后的CurlInterceptor。使用旧的Response后,在我要在其中重新创建Response对象的拦截函数的末尾进行检查。

var responseBodyString = responseBody?.string()

response = response.newBuilder().body(ResponseBody.create(responseBody?.contentType(),responseBodyString.toByteArray())).build()

class CurlInterceptor: Interceptor
{

    var gson = GsonBuilder().setPrettyPrinting().create()

    override fun intercept(chain: Interceptor.Chain): Response {

    Timber.d(" **** ->>Request to server -> ****")

    val request = chain.request()
    var response = chain.proceed(request)

    var curl = "curl -v -X  ${request.method()}"

    val headers = request.headers()

    for ( i in 0..(headers.size() -1) ){
        curl = "${curl} -H \"${headers.name(i)}: ${headers.value(i)}\""
    }

    val requestBody = request.body()
    if (requestBody != null) {
        val buffer = Buffer()
        requestBody.writeTo(buffer)
        var charset: Charset =
            Charset.forName("UTF-8")
        curl = "${curl} --data '${buffer.readString(charset).replace("\n", "\\n")}'"
    }

    Timber.d("$curl ${request.url()}")
    Timber.d("response status code ${response.code()} message: ${response.message()}")

    
    dumbHeaders(response)

    var responseBody = response?.body()

    if(responseBody != null )
    {
        var responseBodyString = responseBody?.string()

            response = response.newBuilder()
                .body(
                    ResponseBody.create(
                        responseBody?.contentType(),
                        responseBodyString.toByteArray()
                    )
                )
                .build()


        responseBodyString = gson.toJson(responseBodyString)

        Timber.d("response json -> \n $responseBodyString")

    }

    Timber.d(" **** << Response from server ****")

    return response
}



fun dumbHeaders(response: Response) {
    try {
        if (response.headers() != null) {

            for (headerName in response.headers().names()) {
                for (headerValue in response.headers(headerName)) {
                    Timber.d("Header $headerName : $headerValue")
                }
            }
        }
    }
catch (ex: Exception){}
}
}

0

尝试像这样更改它:

protected String doInBackground(String... params) {
            try {
                JSONObject root = new JSONObject();
                JSONObject data = new JSONObject();
                data.put("type", type);
                data.put("message", message);
                data.put("title", title);
                data.put("image_url", imageUrl);
                data.put("uid",uid);
                data.put("id", id);
                data.put("message_id", messageId);
                data.put("display_name", displayName);
                root.put("data", data);
                root.put("registration_ids", new JSONArray(receipts));
                RequestBody body = RequestBody.create(JSON, root.toString());
                Request request = new Request.Builder()
                        .url(URL)
                        .post(body)
                        .addHeader("Authorization", "key=" + serverKey)
                        .build();
                Response response = mClient.newCall(request).execute();
                String result = response.body().string();
                Log.d(TAG, "Result: " + result);
                return result;
            } catch (Exception ex) {
                Log.e(TAG,"Exception -> "+ex.getMessage());
            }
            return null;
        }

1
不鼓励仅使用代码的答案。请单击“编辑”并添加一些单词,以概括您的代码如何解决问题,或者说明您的答案与以前的答案有何不同。谢谢
尼克,

0

鉴于响应可能会OutOfMemoryError在文件较大的情况下产生,您可以改为用字节数“窥视”正文并调用该string()方法。

请注意,这会消耗身体。

response.peekBody(500).string());


0

使用字符串后重新创建响应对象

val responseBodyString = response.body()!!。string()

响应= response.newBuilder().body(ResponseBody.create(responseBody?.contentType(),responseBodyString.toByteArray())).build()

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.