Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Same field has two different types gives trouble with Gson converter for Retrofit 2

Here is the json schema:

enter image description here

As you can see, rated can be both boolean and object.

I am using Retrofit 2 and Gson converter. How should I create my model for this schema?

like image 786
Figen Güngör Avatar asked Mar 08 '17 14:03

Figen Güngör


People also ask

What is use of GSON converter factory in retrofit?

Retrofit is a very popular HTTP client library for Android. Using Retrofit makes it easy to parse API response and use it in your application. It has built-in GSON converter that can automatically parse HTTP response into an Object or any other types in Java that can be used in your code.

Which method is used to add the converter to retrofit instance?

Call the created instance of that class (done via create() ) to your Retrofit instance with the method addConverterFactory() . After you've added the converter to Retrofit, it'll automatically take care of mapping the JSON data to your Java objects, as you've seen in the previous blog post.

Does retrofit use GSON?

In Retrofit you configure which converter is used for the data serialization. Typically to serialize and deserialize objects to and from JSON you use an open-source Java library — Gson. Also if you need, you can add custom converters to Retrofit to process XML or other protocols.

What is GsonConverterFactory in retrofit?

Class GsonConverterFactoryA converter which uses Gson for JSON. Because Gson is so flexible in the types it supports, this converter assumes that it can handle all types.


1 Answers

Here's how I solved this issue:

Create a custom type adapter in your model and parse rated manually;

public class AccountState {

    //@SerializedName("rated") //NOPE, parse it manually
    private Integer mRated; //also don't name it rated


    public Integer getRated() {
        return mRated;
    }

    public void setRated(Integer rated) {
        this.mRated = rated;
    }


    public static class AccountStateDeserializer implements JsonDeserializer<AccountState> {

        @Override
        public AccountState deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            AccountState accountState = new Gson().fromJson(json, AccountState.class);
            JsonObject jsonObject = json.getAsJsonObject();

            if (jsonObject.has("rated")) {
                JsonElement elem = jsonObject.get("rated");
                if (elem != null && !elem.isJsonNull()) {
                    if(elem.isJsonPrimitive()){
                        accountState.setRated(null);
                    }else{
                        accountState.setRated(elem.getAsJsonObject().get("value").getAsInt());
                    }
                }
            }
            return accountState ;
        }
    }

}

Here you create your gson with this custom adapter:

final static Gson gson = new GsonBuilder()
            .registerTypeAdapter(AccountState.class, new AccountState.AccountStateDeserializer())
            .create();

Add it to retrofit like that:

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BuildConfig.ENDPOINT)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(okHttpClient)
                .build();

TADADADADADADADDAD!

like image 190
Figen Güngör Avatar answered Nov 01 '22 22:11

Figen Güngör