square / retrofit

A type-safe HTTP client for Android and the JVM
https://square.github.io/retrofit/
Apache License 2.0
43.08k stars 7.31k forks source link

How to send empty object #2739

Open vipulasri opened 6 years ago

vipulasri commented 6 years ago

I am trying to send empty object but retrofit clears out the param with empty or null values. How to make retrofit send empty object or array.

Use case: I am sending additional_fields array param as: additional_fields[0]=2, additional_fields[1]=3 using @Field etc. which is working perfectly. But when I am sending additional_fields=[] with an empty array, retrofit clears out this field and doesn't send it. I am doing it in PATCH call as the user can update its preferences for additional_fields which can have some value or no value.

vipulasri commented 6 years ago

@JakeWharton Please help me out with this.

naturalwarren commented 6 years ago

Write a custom converter?

vipulasri commented 6 years ago

@naturalwarren I didn't find any previously written converter specifically for this. Can you help me on this? And according to me doesn't converters are used while parsing data not posting/sending data.

jnpatel2811 commented 6 years ago

@vipulasri null or empty values won't be send through Retrofit. To send such thing, you need to use custom convertor as : retrofitBuilder.addConverterFactory(GsonConverterFactory.create(customGson)) where customGson is GsonBuilder().serializeNulls().create()

operando commented 6 years ago

@vipulasri I had the same problem.

You can send empty object or array by using FormBody.Builder. I wrote a sample code. please refer. https://gist.github.com/operando/9e7ebeece0e3c8a637580ee100d77834

// Create RequestBody
FormBody.Builder builder = new FormBody.Builder();
List<String> additionalFields = ...;
if (additionalFields.isEmpty()) {
    builder.add("additional_fields[]", "");
} else {
    for (String additionalField : additionalFields) {
        builder.add("additional_fields[]", additionalField);
    }
}

// Send
Api.editApi(builder.build()).enqueue(callback);

// API
interface Api {
    @PUT("put_api")
    Call<Void> editApi(@Body RequestBody body);
}