Imagine the following request:
@POST(\"/recipes/create\")
void createRecipe(@Query(\"recipe\") Recipe recipe, Callback callback);
This is now possible when registering a custom Converter.Factory
that overrides the stringConverter
method, which is called when resolving parameters. The Github issue that @William referred to 2 years ago doesn't seem to be updated since support was added.
Method Javadoc:
Returns a Converter for converting type to a String, or null if type cannot be handled by this factory. This is used to create converters for types specified by @Field, @FieldMap values, @Header, @HeaderMap, @Path, @Query, and @QueryMap values.
The example below delegates to Gson, but in the same way any type of conversion can be applied to the parameters.
Example: GsonStringConverterFactory
class GsonStringConverterFactory
extends Converter.Factory {
private final transient Gson gson;
GsonStringConverterFactory(final Gson gson) {
this.gson = gson;
}
@Override
public Converter, String> stringConverter(final Type type, final Annotation[] annotations, final Retrofit retrofit) {
final TypeAdapter typeAdapter;
typeAdapter = gson.getAdapter(TypeToken.get(type));
return new StringConverter<>(typeAdapter);
}
private static class StringConverter
implements Converter {
private final TypeAdapter typeAdapter;
private StringConverter(final TypeAdapter typeAdapter) {
this.typeAdapter = typeAdapter;
}
@Override
public String convert(final T value)
throws IOException {
/* This works in our case because parameters in this REST api are always some kind of scalar
* and the toJson method converts these to simple json types. */
final String jsonValue;
jsonValue = typeAdapter.toJson(value));
if (jsonValue.startsWith("\"") && jsonValue.endsWith("\"") {
/* Strip enclosing quotes for json String types */
return jsonValue.substring(1, jsonValue.length() - 1);
} else {
return jsonValue;
}
}
}
}
Registering the converter:
To register the custom converter, your Retrofit builder could look something like this:
new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.addConverterFactory(new GsonStringConverterFactory(gson))
.build();