无法让 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() 返回字符串的主要内容,如果未能解决你的问题,请参考以下文章
Retrofit VS OkHttp,谁是最强网络开发框架?