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

问题描述 投票:0回答:10

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

Log

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

java android okhttp
10个回答
310
投票

您可以使用

.string()
功能在
System.out.println()
中打印响应。但最后在
Log.i()
中你使用了
.toString()

因此,请在响应正文上使用

.string()
来打印并获取您请求的响应,例如:

response.body().string();

注意:

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

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

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


55
投票

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

..响应正文是一次性值,只能消耗一次

因此,在调试时,检查器会在“幕后”进行调用,并且主体始终为空。请参阅:https://square.github.io/okhttp/2.x/okhttp/com/squareup/okhttp/ResponseBody.html


21
投票

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

String responseBodyString = response.body.string();

根据应用程序中的需要使用responseBodyString。


3
投票

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

var responseBodyString = responseBody?.string()

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

2
投票

鉴于在大文件的情况下响应可能会产生

OutOfMemoryError
,您可以改为“查看”正文的字节数并调用
string()
方法。

注意这会消耗身体。

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


2
投票

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

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

你可以使用

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

1
投票
   Call call = client.newCall(request);
   return call.execute().body().string();

我们可以通过这些得到回复作为回报


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;
        }

0
投票

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

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

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


0
投票

Kotlin 程序员我在这里等你

 response.body?.charStream()?.readText()?.let { 
                        //Where it refers to Response string
                        callBack.onAPISuccess(it)
                    }

在这里你不能使用 .toString() 函数,并且 .string() 函数在 Kotlin 中不可用,你可以使用 charStream() 并将该 charStream 转换为 readText() 但你必须在传递之前解开整个值。但这永远不会造成问题。

我还没有在java中探索过这些charStream()和readText()函数,但我认为它应该在那里,如果这些函数可用,你可以在java中使用它,因为我刚刚知道java已经弃用了.string()功能。

© www.soinside.com 2019 - 2024. All rights reserved.