Serialize Query-Parameter in Retrofit

前端 未结 4 1989
挽巷
挽巷 2021-02-14 12:17

Imagine the following request:

@POST(\"/recipes/create\")
void createRecipe(@Query(\"recipe\") Recipe recipe, Callback callback);

4条回答
  •  醉话见心
    2021-02-14 12:48

    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 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();
    

提交回复
热议问题