Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I return String or JSONObject from asynchronous callback using Retrofit?

For example, calling

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

cause:

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

I think I must disable gson parsing into POJOs but can't figure out how to do it.

like image 573
lordmegamax Avatar asked Feb 19 '14 13:02

lordmegamax


People also ask

What is retrofit JSON?

Retrofit is a type-safe REST client for Android, Java and Kotlin developed by Square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp.

How does Retrofit work?

Actually retrofit is a wrapper library to turn interfaces in to OkHttp calls. So when you call interface method it just return you to corresponding call object but unless you run enqueue or execute method it will not make a request.

Why do we use Retrofit in Android?

Retrofit is type-safe REST client for Android and Java which aims to make it easier to consume RESTful web services. We'll not go into the details of Retrofit 1. x versions and jump onto Retrofit 2 directly which has a lot of new features and a changed internal API compared to the previous versions.


1 Answers

I figured it out. It's embarrassing but it was very simple... Temporary solution may be like this:

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

But if you want to get directly Callback the Better way is to use Converter.

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

If you know how to improve this code - please feel free to write about it.

like image 74
lordmegamax Avatar answered Sep 21 '22 16:09

lordmegamax