How to handle JSON response of either a list of ob

2019-08-28 06:19发布

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?

3条回答
聊天终结者
2楼-- · 2019-08-28 06:33

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();
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-08-28 06:40

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

查看更多
Deceive 欺骗
4楼-- · 2019-08-28 06:56

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.

查看更多
登录 后发表回答