ads
ads

Reputation: 1723

How to handle JSON response of either a list of objects or a single object using retrofit?

I am calling a REST service (not mine) using retrofit which either returns a list of objects (if there are multiple) or a single object (if one). I was able to find a similar issue here however the suggestion is to change the API which i don't have control of. I also read this thread which seems to be a good approach but is there a way to handle this using Retrofit?

Upvotes: 1

Views: 2094

Answers (3)

ads
ads

Reputation: 1723

While the answer from @pirho seems to be applicable, I found out a different and simple solution which worked for me. Hopefully it may help others as well.

    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(baseUrl)
            .addConverterFactory(JacksonConverterFactory.create(mapper))
            .client(okHttpClient)
            .build();

Upvotes: 2

pirho
pirho

Reputation: 12215

As the author of the 2nd post you referred I also refer to the implementation of PostArrayOrSingleDeserializer described in that answer of mine.

When using Gson with Retrofit (Retrofit's converter-gson) you just need to register the adapter with custom Gson instance and build the Retrofit instance with that Gson instance, see below example helper class:

public class MyRetrofit {
    public static MyAPI getMyApi() {
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(Object.class,
                        new ObjectArrayOrSingleDeserializer())
                .create();
        Retrofit retrofit = new Retrofit.Builder()  
                .baseUrl("https://example.org")
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
        return retrofit.create(MyAPI.class);
    }
}

So the Object in the JsonDeserializer named ObjectArrayOrSingleDeserializer is the DTO you need to check for single instance or array. Replace Object with corresponding DTO and modify deserializer accordingly.

Upvotes: 0

vikas kumar
vikas kumar

Reputation: 11018

You can get the API response data as Map<String, JsonElement> in response and then parse it based on your requirement directly. As you can check here if JsonElement is JsonArray

for ex:

public fun parseData(val jsonElement:JsonElement){

  val gson = Gson()

  if(jsonElementFromServer.isJsonArray()){
    //here you can just parse it into some list of array

  }else{
    //here you can parse using gson to single item element or model 

  }

}

JsonElement ref

Using Gson to get list of items or single model

Upvotes: 0

Related Questions