OkHttps response.body.toString () kann keine Zeichenfolge zurückgeben


77

Ich versuche, mit OkHttp einige JSON-Daten abzurufen, und kann nicht herausfinden, warum, wenn ich versuche, das zu protokollieren, response.body().toString()was ich bekommeResults:﹕ 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

Ich weiß nicht, was ich hier falsch mache. Wie bekomme ich die Antwortzeichenfolge?



Sie drucken einfach ein Objekt und Ihre Spur bestätigt es.
Michele d'Amico

3
Lesen Sie das Dokument. Die Methode, die Sie suchen, iststring
njzk2

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

Antworten:


33

Nur für den Fall, dass jemand auf die seltsame Sache stößt wie ich. Ich führe meinen Code während der Entwicklung im Debug-Modus und anscheinend seit OKHttp 2.4 aus

..der Antwortkörper ist ein One-Shot-Wert, der nur einmal verbraucht werden darf

Beim Debuggen wird der Inspektor "hinter den Kulissen" angerufen, und der Körper ist immer leer. Siehe: https://square.github.io/okhttp/3.x/okhttp/okhttp3/ResponseBody.html


3
Wie rufst du an, .string()ohne einen Antwortkörper zu verbrauchen?
osrl

1
Sie sind sich nicht sicher, ob Sie .string () aufrufen können, ohne den Antworttext zu verbrauchen, aber als Problemumgehung. Sie können jedoch dem Muster folgen, das der Protokollierungs-Interceptor von okhttp verwendet, um dies zu tun: github.com/square/okhttp/blob/master/okhttp- Logging-Interceptor /…
Liampronan

1
Es bedeutet, dass wir Okhttp-Antworttext nicht debuggen können

1
Sie können den Antworttext auf Protokoll mit deaktiviertem Debug drucken
Oded Regev

3
Was für ein böses Verhalten! Ich weiß, wie wenig hilfreich diese Art von Kommentaren ist, möchte mich trotzdem bei Ihnen bedanken
Sergei Voitovich

236

Sie haben die .string()Funktion, um die Antwort auszudrucken System.out.println(). Aber endlich benutzt Log.i()du .toString().

Verwenden Sie also bitte .string()den Antworttext, um die Antwort Ihrer Anfrage auszudrucken und zu erhalten, z.

response.body().string();

HINWEIS:

  1. .toString(): Dies gibt Ihr Objekt im Zeichenfolgenformat zurück.

  2. .string(): Dies gibt Ihre Antwort zurück.

Ich denke, das löst dein Problem ... Richtig.


2
Keine string () Funktion mehr, was jetzt?
eC Droid

@eCDroid " Keine string () -Funktion mehr " Bist du sicher?
SHOLE


10

Das response.body,.string()kann nur einmal konsumiert werden. Bitte verwenden Sie wie folgt:

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

1
Dies kann einen OutOfMemoryError für eine große Antwort (dh Zip-Datei)
auslösen

1

Es folgt mein modifizierter CurlInterceptor. Überprüfen Sie das Ende der Intercept-Funktion, an der ich das Response-Objekt neu erstelle, nachdem ich die alte Response verbraucht habe.

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

versuchen Sie es zum Beispiel so zu ändern:

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
Von Nur-Code-Antworten wird abgeraten. Klicken Sie auf Bearbeiten und fügen Sie einige Wörter hinzu, die zusammenfassen, wie Ihr Code die Frage beantwortet, oder erklären Sie möglicherweise, wie sich Ihre Antwort von der vorherigen Antwort / den vorherigen Antworten unterscheidet. Danke
Nick

0

Da eine Antwort OutOfMemoryErrorbei großen Dateien möglicherweise zu einer Antwort führen kann , können Sie stattdessen den Body mit der Anzahl der Bytes "spähen" und die string()Methode aufrufen .

Beachten Sie, dass dies den Körper verbraucht.

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


0

Erstellen Sie das Antwortobjekt neu, nachdem Sie die Zeichenfolge verbraucht haben

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

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.