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

Posted

技术标签:

【中文标题】无法让 OkHttp 的 response.body.toString() 返回字符串【英文标题】:Can't get OkHttp's response.body.toString() to return a string 【发布时间】:2015-04-02 17:37:19 【问题描述】:

我正在尝试使用 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);

我不知道我在这里做错了什么。如何获取响应字符串?

【问题讨论】:

可能是http://***.com/questions/5769717/how-can-i-get-an-http-response-body-as-a-string-in-java的副本 您只需打印一个对象并通过您的跟踪确认它。 阅读文档。您正在寻找的方法是string val responseBodyString = response.body()!!.string() response = response.newBuilder() .body(ResponseBody.create(responseBody?.contentType(), responseBodyString.toByteArray())) .build() 请看这个链接***.com/a/70824088/12272687 【参考方案1】:

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

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

response.body().string();

注意:

    .toString():这会以字符串格式返回您的对象。

    .string():这将返回您的响应。

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

【讨论】:

没有 string() 函数了,现在怎么办? @eCDroid "没有更多的 string() 函数" 你确定吗? 根据文档`自动关闭ResponseBody。`您需要记住,调用此方法后您将无法读取响应【参考方案2】:

以防万一有人碰到和我一样奇怪的东西。我在 Debug Mode 的开发过程中运行我的代码,显然是从 OKHttp 2.4

..响应正文是一次性值,只能使用一次

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

【讨论】:

如何在不消耗响应正文的情况下调用.string() 不确定是否可以在不消耗响应正文的情况下调用 .string(),但可以作为一种解决方法,但您可以按照 okhttp 的日志拦截器执行此操作的模式:github.com/square/okhttp/blob/master/okhttp-logging-interceptor/… 表示我们无法调试Okhttp响应体 您可以在禁用调试的情况下将响应正文打印到日志 多么邪恶的行为!我知道这种cmets有多么无用,不过还是要谢谢你【参考方案3】:

response.body,.string() 只能使用一次。 请按如下方式使用:

String responseBodyString = response.body.string();
use the responseBodyString as needed in your application.

【讨论】:

这可能会触发一个 OutOfMemoryError 用于大型响应(即 zip 文件)【参考方案4】:

而不是使用 .toString() 返回一个对象

String results = response.body().toString();

你可以使用

String results = response.body().string();

【讨论】:

【参考方案5】:

以下是我修改后的 CurlInterceptor。检查拦截函数的结尾,我在使用旧的响应后重新创建响应对象。

var responseBodyString = responseBody?.string()

响应 = response.newBuilder() 。身体( 响应体.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)


【讨论】:

【参考方案6】:

尝试像这样改变它,例如:

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;
        

【讨论】:

不鼓励仅使用代码的答案。请单击edit 并添加一些词来总结您的代码如何解决问题,或者解释您的答案与之前的答案/答案有何不同。谢谢【参考方案7】:

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

注意这会消耗身体。

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

【讨论】:

【参考方案8】:

消费字符串后重新创建响应对象

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

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

【讨论】:

以上是关于无法让 OkHttp 的 response.body.toString() 返回字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 OkHttp 连接 SPDY 网站?

OkHttp3-连接(Connections)

Retrofit VS OkHttp,谁是最强网络开发框架?

学会Retrofit+OkHttp+RxAndroid三剑客的使用,让自己紧跟Android潮流的步伐

无法从缓存 okHttp 和改造中加载数据

如何让OkHttp从Jersey获取参数并在Interceptor中使用?