Retrofit has provided users with six converters, as follows:
- Gson:
com.squareup.retrofit2:converter-gson
- Jackson:
com.squareup.retrofit2:converter-jackson
- Moshi:
com.squareup.retrofit2:converter-moshi
- Protobuf:
com.squareup.retrofit2:converter-protobuf
- Wire:
com.squareup.retrofit2:converter-wire
- Simple XML:
com.squareup.retrofit2:converter-simplexml
- Scalars (primitives, boxed, and String):
com.squareup.retrofit2:converter-scalars
However, the latest project requires that String and JSON should be sent and received at the same time. After the current Converter is set, we need to customize the Converter. However, the above Converter already has String and JSON processing methods. We can combine com.squareup.retrofit2: Converter gson and com.squareup.retrofit2: Converter scalars to achieve the project requirements.
Requested string conversion:
public class StringRequestBodyConverter<T> implements Converter<T, RequestBody> { private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain; charset=UTF-8"); StringRequestBodyConverter() { } @Override public RequestBody convert(T value) throws IOException { return RequestBody.create(MEDIA_TYPE, String.valueOf(value)); } }
JSON conversion of response:
public class JsonResponseBodyConverter<T> implements Converter<ResponseBody, T> { private final Gson gson; private final TypeAdapter<T> adapter; JsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) { this.gson = gson; this.adapter = adapter; } @Override public T convert(ResponseBody value) throws IOException { JsonReader jsonReader = gson.newJsonReader(value.charStream()); try { return adapter.read(jsonReader); } finally { value.close(); } } }
The implementation factory of Converter:
public class ExtConverterFactory extends Converter.Factory{ private final Gson gson; public static ExtConverterFactory create() { return new ExtConverterFactory(new Gson()); } private ExtConverterFactory(Gson gson) { this.gson = gson; } @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new JsonResponseBodyConverter<>(gson, adapter); } @Override public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { if (type == String.class || type == boolean.class || type == Boolean.class || type == byte.class || type == Byte.class || type == char.class || type == Character.class || type == double.class || type == Double.class || type == float.class || type == Float.class || type == int.class || type == Integer.class || type == long.class || type == Long.class || type == short.class || type == Short.class) { return new StringRequestBodyConverter(); } return null; } }
After that, you can initialize Retrofit as follows to send String and receive JSON.
Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(ExtConverterFactory.create()) .client(new OkHttpClient()) .baseUrl("http://api.test.com/") .build(); NetApi netApi = retrofit.create(NetApi.class);
Reference documents: https://square.github.io/retrofit/