Không thể nhận được response.body.toString () của OkHttp để trả về một chuỗi


80

Tôi đang cố lấy một số dữ liệu json bằng OkHttp và không thể tìm ra lý do tại sao khi tôi thử ghi lại response.body().toString()những gì tôi nhận được là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);

Nhật ký

Tôi không biết mình đang làm gì sai ở đây. Làm cách nào để lấy chuỗi phản hồi?



Bạn chỉ cần in một đối tượng và dấu vết của bạn xác nhận nó.
Michele d'Amico

3
đọc tài liệu. phương pháp bạn đang tìm kiếm làstring
njzk2

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

Câu trả lời:


35

Đề phòng trường hợp ai đó va phải điều kỳ lạ giống như tôi. Tôi chạy mã của mình trong quá trình phát triển ở Chế độ gỡ lỗi và dường như kể từ OKHttp 2.4

.. phần thân phản hồi là giá trị một lần duy nhất có thể được sử dụng một lần

Vì vậy, khi gỡ lỗi có một cuộc gọi "phía sau hiện trường" từ thanh tra và phần thân luôn trống. Xem: https://square.github.io/okhttp/3.x/okhttp/okhttp3/ResponseBody.html


3
làm thế nào để bạn gọi .string()mà không tốn cơ thể phản hồi?
osrl

1
Không chắc liệu bạn có thể gọi .string () mà không sử dụng phần thân phản hồi hay không, nhưng bạn có thể làm theo mẫu mà trình chặn ghi nhật ký của okhttp sử dụng để thực hiện việc này: github.com/square/okhttp/blob/master/okhttp- logging-interceptor /…
liampronan

1
Nó có nghĩa là chúng ta không thể gỡ lỗi Okhttp cơ thể phản ứng

1
Bạn có thể in cơ thể đáp ứng với Log với gỡ lỗi khuyết tật
Oded Regev

3
Thật là một hành vi xấu xa! Tôi biết loại nhận xét này vô ích như thế nào, tuy nhiên, tôi muốn cảm ơn bạn
Sergei Voitovich

241

Bạn có .string()chức năng sử dụng để in phản hồi trong System.out.println(). Nhưng cuối cùng ở Log.i()bạn đang sử dụng .toString().

Vì vậy, vui lòng sử dụng .string()trên nội dung phản hồi để in và nhận phản hồi yêu cầu của bạn, như:

response.body().string();

GHI CHÚ:

  1. .toString(): Điều này trả về đối tượng của bạn ở định dạng chuỗi.

  2. .string(): Điều này trả về phản hồi của bạn.

Tôi nghĩ rằng điều này giải quyết vấn đề của bạn ... Đúng.


2
Không còn hàm string (), làm gì bây giờ?
eC Droid

@eCDroid " Không còn hàm string () " Bạn có chắc không?
sHOLE

1
Theo tài liệu `Tự động đóng ResponseBody. 'Bạn cần lưu ý rằng bạn sẽ không thể đọc phản hồi sau khi gọi phương thức này
Roman Nazarevych

10

Chỉ response.body,.string()có thể được tiêu thụ một lần. Vui lòng sử dụng như bên dưới:

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

1
Điều này có thể kích hoạt một OutOfMemoryError cho một phản ứng lớn (tức là nén tập tin)
IgorGanapolsky

1

Sau đây là CurlInterceptor đã sửa đổi của tôi. Kiểm tra phần cuối của hàm chặn mà tôi đang tạo lại đối tượng Phản hồi sau khi sử dụng Phản hồi cũ.

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

cố gắng thay đổi nó như vậy, ví dụ:

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
Câu trả lời chỉ có mã không được khuyến khích. Vui lòng nhấp vào chỉnh sửa và thêm một số từ tóm tắt cách mã của bạn giải quyết câu hỏi hoặc có thể giải thích câu trả lời của bạn khác với câu trả lời / câu trả lời trước đó như thế nào. Cảm ơn
Nick

0

Cho rằng một phản hồi có thể tạo ra một OutOfMemoryErrortrong những trường hợp tệp lớn, thay vào đó, bạn có thể "xem trước" phần nội dung bằng số byte và gọi string()phương thức.

Lưu ý rằng điều này sẽ làm tiêu hao cơ thể.

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


0

Tạo lại đối tượng phản hồi sau khi sử dụng chuỗi

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

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.