web-dev-qa-db-fra.com

Retrofit callback get corps de réponse

Je teste Retrofit pour le comparer à Volley et j'ai du mal à obtenir la réponse à mes demandes. Par exemple, je fais quelque chose comme ça:

RestAdapter restAdapter = new RestAdapter.Builder()
            .setEndpoint("http://localhost:8080")
            .build();

MyService service = restAdapter.create(MyService.class);
service.getToto("toto", new Callback<Toto>() {

        @Override
        public void success(Toto toto, Response response) {
            // Try to get response body
            BufferedReader reader = null;
            StringBuilder sb = new StringBuilder();
            try {
                reader = new BufferedReader(
                    new InputStreamReader(response.getBody().in()));
                String line;
                try {
                    while ((line = reader.readLine()) != null) {
                        sb.append(line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            String result = sb.toString();
        }

        @Override
        public void failure(RetrofitError error) {}
    });

Cela fonctionne, l'objet toto est défini, mais à des fins de test, je souhaite également afficher la réponse JSON renvoyée par le serveur.

J'essaie donc de lire le InputStream de response.getBody() qui est un TypedInputStream. Malheureusement, je reçois toujours un IOException : Stream is closed.

J'ai essayé d'utiliser la classe tils de Retrofit mais j'obtiens la même erreur IOException.

45
Kerwan

Les crochets angulaires de callback à l'intérieur écrivent "Réponse" puis extraient le flux de cette réponse.

service.getToto("toto", new Callback<Response>() {
    @Override
    public void success(Response result, Response response) {

        //Try to get response body
        BufferedReader reader = null;
        StringBuilder sb = new StringBuilder();
        try {

            reader = new BufferedReader(new InputStreamReader(result.getBody().in()));

            String line;

            try {
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


        String result = sb.toString();
    }

    @Override
    public void failure(RetrofitError error) {

    }
});
52
Nitesh Khatri

Avant la modernisation 2.

   String bodyString = new String(((TypedByteArray) response.getBody()).getBytes());

Retrofit 2.

 String  bodyString = new String(response.body().bytes());
29
shiami

Si vous définissez .setLogLevel(RestAdapter.LogLevel.FULL) sur le RestAdapter que vous utilisez pour créer le service, vous devez obtenir le résultat de la réponse JSON brut dans la console de débogage.

RestAdapter restAdapter = new RestAdapter.Builder()
    .setServer("http://my_lovely_api.com")
    .setLogLevel(RestAdapter.LogLevel.FULL)
    .build();

mService = restAdapter.create(MyService.class);

Si vous voulez faire quelque chose de différent avec cette réponse brute, vous pouvez toujours utiliser le code que vous avez dans votre bloc de succès pour créer une chaîne JSON, en supposant que vous conserviez le LogLevel.FULL Dans la méthode setLogLevel, si pas alors il ne sera pas analyser le InputStream de response.getBody().in() comme il a déjà été lu et fermé.

23
droppin_science

J'ai récemment rencontré un problème similaire. Je voulais regarder un json dans le corps de la réponse, mais je ne voulais pas traiter avec le TypedByteArray de Retrofit. J'ai trouvé que le moyen le plus rapide de contourner ce problème était de créer un Pojo (Plain Old Java Object)) avec un seul champ String. Plus généralement, vous feriez un Pojo avec un seul champ correspondant aux données que vous voulu regarder.

Par exemple, disons que je faisais une demande dans laquelle la réponse du serveur était une seule chaîne dans le corps de la réponse, appelée "access_token".

Mon Pojo ressemblerait à ceci:

public class AccessToken{
    String accessToken;

    public AccessToken() {}

    public String getAccessToken() {
        return accessToken;
    }
} 

et puis mon rappel ressemblerait à ceci

Callback<AccessToken> callback = new Callback<AccessToken>() {
   @Override
   public void success(AccessToken accessToken, Response response) {
       Log.d(TAG,"access token: "+ accessToken.getAccessToken());
   }

   @Override
   public void failure(RetrofitError error) {
       Log.E(TAG,"error: "+ error.toString());
   }
};

Cela vous permettra de regarder ce que vous avez reçu dans la réponse.

3
Michael Alan Huff

S'il vous plaît, n'utilisez pas les flux et straemReaders pour cela. Utilisez des solutions intelligentes comme le fait le carré:

private Response logAndReplaceResponse(String url, Response response, long elapsedTime)

http://www.programcreek.com/Java-api-examples/index.php?source_dir=retrofit-jaxrs-master/retrofit/src/main/Java/retrofit/RestAdapter.Java

exemple:

private String getResponseBody(Response response) {
    String result = "";
    //Try to get response body
    if (response.getBody() instanceof TypedByteArray) {
        TypedByteArray b = (TypedByteArray) response.getBody();
        result = new String(b.getBytes());
    }
    return result;
}
3
Kirill Vashilo

Une autre solution serait de faire quelque chose comme ceci:

  private static String bodyAsString(RequestBody body) {
    try {
      Buffer buffer = new Buffer();
      body.writeTo(buffer);
      return buffer.readString(body.contentType().charset());
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

Extrait de https://github.com/square/okhttp/blob/master/okcurl/src/test/Java/com/squareup/okhttp/curl/MainTest.Java#L93-L101

1
loeschg

Avec la version 2.1.0, vous pouvez obtenir le contenu en tant que

public void onResponse(Call<T> call, Response<T> response) {
    String errorString = response.errorBody().string();
}
1
Ravi Selvaraj

Fais-le comme ça:

ModelClass modelclass=response.response.body()
System.out.println("****************-----retro rsp----1-------"+modelclass.getMessage());
0
Nishanth S Babu