Не вдається отримати відповідь OkHttp.body.toString () для повернення рядка


82

Я намагаюся отримати деякі дані JSON за допомогою OkHttp, і не можу зрозуміти, чому, коли я намагаюся реєструвати те, 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

Відповіді:


35

Про всяк випадок, коли хтось наткнеться на те саме дивне, що і я. Я запускаю свій код під час розробки в режимі налагодження і, мабуть, з OKHttp 2.4

.. тіло відповіді - це одноразове значення, яке може бути використано лише один раз

Отже, коли під час налагодження інспектор дзвонить "за кадром", і тіло завжди порожнє. Див .: https://square.github.io/okhttp/3.x/okhttp/okhttp3/ResponseBody.html


3
як ти телефонуєш, .string()не споживаючи тіло відповіді?
osrl

1
Не впевнений, що ви можете зателефонувати .string (), не витрачаючи тіло відповіді, але як обхідне рішення, але ви можете слідувати шаблону, за допомогою якого для цього використовується перехоплювач журналу okhttp
liampronan

1
Це означає, що ми не можемо налагодити тіло відповіді

1
Ви можете роздрукувати тіло відповіді в журналі з відключеною налагодженням
Одед Регев

3
Яка жорстока поведінка! Я знаю, наскільки корисними є такі коментарі, я все ж хочу подякувати вам
Сергій Войтович

242

У вас є .string()функція use для друку відповіді у System.out.println(). Але нарешті Log.i()ти використовуєш .toString().

Тож, будь ласка, використовуйте .string()на тілі відповіді, щоб надрукувати та отримати відповідь на ваш запит, наприклад:

response.body().string();

ПРИМІТКА:

  1. .toString(): Це повертає ваш об'єкт у форматі рядка.

  2. .string(): Це повертає вашу відповідь.

Я думаю, це вирішить вашу проблему ... Правильно.


2
Більше немає функції string (), що тепер?
eC Droid

@eCDroid " Більше немає функції string () " Ви впевнені?
sHOLE

1
Відповідно до документації `Закриває ResponseBody автоматично.` Потрібно мати на увазі, що Ви не зможете прочитати відповідь після виклику цього методу
Роман Назаревич,

10

Банку response.body,.string()можна вживати лише один раз. Будь ласка, використовуйте, як показано нижче:

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

1
Це може спричинити OutOfMemoryError для великої відповіді (тобто ZIP-файлу)
Ігор Ганапольський,

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 = response.newBuilder () .body (ResponseBody.create (responseBody? .contentType (), responseBodyString.toByteArray ())) .build ()

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.