Comment puis-je retourner Ssortingng ou JSONObject à partir d’un rappel asynchrone à l’aide de Retrofit?

Par exemple, appeler

api.getUserName(userId, new Callback() {...}); 

cause:

 retrofit.RetrofitError: retrofit.converter.ConversionException: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a ssortingng but was BEGIN_OBJECT at line 1 column 2 

Je pense que je dois désactiver l’parsing syntaxique de gson dans les POJO mais je n’arrive pas à comprendre comment le faire.

Je l’ai compris. C’est embarrassant mais c’était très simple … Une solution temporaire peut être comme ceci:

  public void success(Response response, Response ignored) { TypedInput body = response.getBody(); try { BufferedReader reader = new BufferedReader(new InputStreamReader(body.in())); SsortingngBuilder out = new SsortingngBuilder(); Ssortingng newLine = System.getProperty("line.separator"); Ssortingng line; while ((line = reader.readLine()) != null) { out.append(line); out.append(newLine); } // Prints the correct Ssortingng representation of body. System.out.println(out); } catch (IOException e) { e.printStackTrace(); } } 

Mais si vous voulez recevoir directement Callback, la meilleure façon est d’utiliser Converter .

 public class Main { public interface ApiService { @GET("/api/") public void getJson(Callback callback); } public static void main(Ssortingng[] args) { RestAdapter restAdapter = new RestAdapter.Builder() .setClient(new MockClient()) .setConverter(new SsortingngConverter()) .setEndpoint("http://www.example.com").build(); ApiService service = restAdapter.create(ApiService.class); service.getJson(new Callback() { @Override public void success(Ssortingng str, Response ignored) { // Prints the correct Ssortingng representation of body. System.out.println(str); } @Override public void failure(RetrofitError retrofitError) { System.out.println("Failure, retrofitError" + retrofitError); } }); } static class SsortingngConverter implements Converter { @Override public Object fromBody(TypedInput typedInput, Type type) throws ConversionException { Ssortingng text = null; try { text = fromStream(typedInput.in()); } catch (IOException ignored) {/*NOP*/ } return text; } @Override public TypedOutput toBody(Object o) { return null; } public static Ssortingng fromStream(InputStream in) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); SsortingngBuilder out = new SsortingngBuilder(); Ssortingng newLine = System.getProperty("line.separator"); Ssortingng line; while ((line = reader.readLine()) != null) { out.append(line); out.append(newLine); } return out.toSsortingng(); } } public static class MockClient implements Client { @Override public Response execute(Request request) throws IOException { URI uri = URI.create(request.getUrl()); Ssortingng responseSsortingng = ""; if (uri.getPath().equals("/api/")) { responseSsortingng = "{result:\"ok\"}"; } else { responseSsortingng = "{result:\"error\"}"; } return new Response(request.getUrl(), 200, "nothing", Collections.EMPTY_LIST, new TypedByteArray("application/json", responseSsortingng.getBytes())); } } } 

Si vous savez comment améliorer ce code, n’hésitez pas à écrire à ce sujet.

Une solution possible serait d’utiliser JsonElement comme type de Callback ( Callback ). Dans votre exemple original:

 api.getUserName(userId, new Callback() {...}); 

Dans la méthode de réussite, vous pouvez convertir JsonElement en une Ssortingng ou en un object JsonObject .

 JsonObject jsonObj = element.getAsJsonObject(); Ssortingng strObj = element.toSsortingng(); 

Retrofit 2.0.0-beta3 ajoute un module converter-scalars -scalars qui fournit Converter.Factory pour convertir Ssortingng , les 8 types primitifs et les 8 types primitifs encadrés en tant que corps text/plain . Installez ceci avant votre convertisseur normal pour éviter de transmettre ces simples scalaires, par exemple, à l’aide d’un convertisseur JSON.

Donc, commencez par append le module converter-scalars build.gradle fichier build.gradle pour votre application.

 dependencies { ... // use your Retrofit version (requires at minimum 2.0.0-beta3) instead of 2.0.0 // also do not forget to add other Retrofit module you needed comstack 'com.squareup.retrofit2:converter-scalars:2.0.0' } 

Ensuite, créez votre instance Retrofit comme ceci:

 new Retrofit.Builder() .baseUrl(BASE_URL) // add the converter-scalars for coverting Ssortingng .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build() .create(Service.class); 

Maintenant, vous pouvez utiliser la déclaration API comme ceci:

 interface Service { @GET("/users/{id}/name") Call userName(@Path("userId") Ssortingng userId); // RxJava version @GET("/users/{id}/name") Observable userName(@Path("userId") Ssortingng userId); } 

La réponse peut être beaucoup plus courte que celle déjà mentionnée et ne nécessite aucune bibliothèque supplémentaire:

Dans la déclaration, utilisez la Response comme suit:

 ... Callback callback); 

Et tout en gérant la réponse:

 @Override public void success(Response s, Response response) { new JSONObject(new Ssortingng(((TypedByteArray) response.getBody()).getBytes())) } 

Quand @lordmegamax répond complètement, il y a beaucoup plus belle solution qui vient de

Okio est une nouvelle bibliothèque qui complète java.io et java.nio

d’autres projets de carrés qui sont déjà serrés avec la retrofit à retrofit et vous n’avez donc pas besoin d’append de nouvelles dépendances et cela doit être fiable:

 ByteSsortingng.read(body.in(), (int) body.length()).utf8(); 

ByteSsortingng est une séquence immuable d’octets. Pour les données de caractères, Ssortingng est fondamental. ByteSsortingng est le frère perdu depuis longtemps de Ssortingng, ce qui facilite le traitement des données binarys en tant que valeur. Cette classe est ergonomique: elle sait encoder et se décoder en hex, base64 et UTF-8.

Exemple complet:

 public class SsortingngConverter implements Converter { @Override public Object fromBody(TypedInput body, Type type) throws ConversionException { try { return ByteSsortingng.read(body.in(), (int) body.length()).utf8(); } catch (IOException e) { throw new ConversionException("Problem when convert ssortingng", e); } } @Override public TypedOutput toBody(Object object) { return new TypedSsortingng((Ssortingng) object); } } 

Voici ce que j’ai fait, après avoir fouillé dans le débogueur. Note: ceci est pour le récupérer dans un rappel d’erreur, pas le rappel de succès.

Vous verrez que le type de succès est trouvé en appelant retrofitError.getSuccessType() et retourne et object de type Type

Vous pouvez alors appeler retrofitError.getBodyAs(YourType.class) tout ce que je devais faire, car pour moi, c’est toujours la classe à laquelle je m’attendais.

Voici la réponse à une ligne:

 retrofitError.getBodyAs(retrofitError.getSuccessType()) 

Maintenant, je vais noter que je n’ai rien à faire de tel en ce qui concerne le rappel de succès car il fonctionne déjà comme par magie.

Pour obtenir l’appel JSONObject ou JSONArray

vous pouvez créer une fabrique personnalisée ou la copier ici: https://github.com/marcinOz/Retrofit2JSONConverterFactory