Default/Constant values for POST/PUT arguments with Retrofit

3.7k Views Asked by At

Using the Retrofit REST Client library from Square, is there anyway of providing default/constant values for POST/PUT fields in a call.

I know about including constant query parameters by simply including them in the path, but this work for Body parameters.

I have an API that looks similar to:

POST /api/create
type=constanta&value={value}

POST /api/create
type=constantb&value={value}&otherValue={otherValue}

where the second variant requires an additional argument to be supplied. Rather than having a single java method that took all three arguments, I was hoping to be able to elide the constants from the method call, something like:

create(String value);
create(String value, String otherValue);

and have retrofit inject the type argument constant.

Given that adding @FormUrlEncoded can be added to modify how the body is encoded, if it's not natively supported by Retrofit, is there anyway of adding my own annotation and injecting such default values? ( It doesn't appear that RequestInterceptor allows one to modify the body.. ).

2

There are 2 best solutions below

0
On BEST ANSWER

Maybe one option would be to send an object, which encapsulates all your values, instead of all string values separately? The object would implement your default values.

For example, you could create a class:

public class CreateObject {
    private String type = "constant";
    private String value;
    private String otherValue;

    public CreateObject(String value, String otherValue) {
        this.value = value;
        this.otherValue = otherValue;
    }
}

Your class handles your constant. You could just set it to a default value "constant", like I did above, or set it on the fly in the constructor.

Now all you've to do is to create the object with the values and make the request with Retrofit. Instead of using the string values directly, just pass the object. Your interface could look like this:

public interface CreateService {
    @POST("/api/create")
    void create(@Body CreateObject create, Callback<CreateObject> cb);
}

The request implementation like this:

CreateObject create = new CreateObject("value", "otherValue");
createService.create(create, new Callback<CreateObject)() {…});

This should include all three of your values in the request body, if they are set. If a value is null, it won't be included in the request body. Based on your two examples above, you would now only need one interface method. Which values are sent is based on the createObject you pass on. For example, if you set otherValue as null, it won't be part of the request body.

My examples were modified from: https://futurestud.io/blog/retrofit-send-objects-in-request-body/

3
On

Is it possible for you to use Guava or Java 8 Optional as second argument in method? Then if that argument will be absent you can just ignore it