Retrofit custom converter

I am trying to use a custom converter for Retrofit

RestAdapter.Builder builder = new RestAdapter.Builder() .setEndpoint(BuildConfig.BASE_SERVER_ENDPOINT) .setClient(new OkClient(client)).setConverter(new CitationResponseConverter()) .setLogLevel(RestAdapter.LogLevel.FULL); 

below is my custom converter

 public class CitationResponseConverter implements Converter { @Override public Object fromBody(TypedInput typedInput, Type type) throws ConversionException { try { InputStream in = typedInput.in(); // convert the typedInput to String String string = fromStream(in); in.close(); // we are responsible to close the InputStream after use if (String.class.equals(type)) { return string; } else { return new Gson().fromJson(string, type); // convert to the supplied type, typically Object, JsonObject or Map<String, Object> } } catch (Exception e) { // a lot may happen here, whatever happens throw new ConversionException( e); // wrap it into ConversionException so retrofit can process it } } @Override public TypedOutput toBody(Object object) { return null; } private static String fromStream(InputStream in) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder out = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { out.append(line); out.append("\r\n"); } return out.toString(); } } 

I get the following error

 retrofit.RetrofitError: method POST must have a request body. 

when trying to make this api call

  @POST("/service/citations") Observable<CitationMain> getCitations(@Body CitationRequestBody body); 

I believe that the converter overrides the api call request, how can I avoid this and pass the request body defined in the retrofit service.

Answer:

 { "citations": [ { "coverdatestart": "2015-05-01", "coverimage": [ "09699961/S0969996115X00040/cov200h.gif", "09699961/S0969996115X00040/cov150h.gif" ], "pubyear": "2015", "refimage": [ "09699961/S0969996115X00040/S0969996115000522/gr1-t.gif", "09699961/S0969996115X00040/S0969996115000522/gr1.jpg" ], "volissue": "Volume 77", "volume": "77" }, { "pubdatetxt": "19700101", "refimage": "mma:otto_4_9781455748600/9781455748600_0020", } ] } 
+7
json android gson parsing retrofit
source share
1 answer

I would do something like this:

 public class StringList extends ArrayList<String> { // Empty on purpose. The class is here only to be recognized by Gson } public class CitationMain { @SerializedName("field_name_here") StringList values; // Your other fields } 

Then when creating the RestAdapter:

 public class StringListDeserializer implements JsonDeserializer<StringList> { @Override public StringList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { StringList value = new StringList(); if (json.isJsonArray()) { for (JsonElement element : json.getAsJsonArray()) { value.add(element.getAsString()); } } else { value.add(json.getAsString()); } return value; } } 

And then:

 Gson gson = new GsonBuilder() .registerTypeAdapter(StringList.class, new StringListDeserializer()) .create(); RestAdapter.Builder builder = new RestAdapter.Builder() //... .setConverter(new GsonConverter(gson)); 

This is not ideal, since the object is ordinary, but any other solution that I can think of now is much more complicated.

Here, the deserializer is registered specifically for fields declared as StringList , and will handle the case of a single string, as well as the case of an array of strings. Any other type of field will use the default deserialization process.

+4
source share

All Articles