Stan
Stan

Reputation: 6551

Unable to create converter for class..., Retrofit2, Realm4 and GSON

Its not a question. Its explanation of another way to get this exception.
So I use Retrofit 2 and it had been properly set up:

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile "com.squareup.retrofit2:converter-scalars:2.3.0"
compile 'com.squareup.retrofit2:converter-gson:2.3.0'

I have this Retrofit config in my ApiHelper:

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

Realm 4.1.1:

dependencies {
    classpath "io.realm:realm-gradle-plugin:4.1.1"
}

and GSON in my project.

However I'm getting exception:

java.lang.IllegalArgumentException: Unable to create converter for class<br> 

from ApiHelper right before request happens.

EXPLANATION:
This exception is not about Retrofit really (but most answers are about Retrofit configuration). Its about Realm. From version 4.0 they've added support for RealmList of primitives. And my response class contains such fields:

@SerializedName("bad_habits")
private RealmList<Integer> badHabitIds;

and actually this is the reason of the exception! Realm docs says

Lists of primitives do not support lists-of-lists, querying and import using the Realm.create*FromJson API’s.

but that appears unclearly to me. So if you are getting such exception and you has everything set up (Retrofit/GSON/gradle.build I mean) most probably its due to lists of primitives if you are using it. They are supported but its deserialization is not.

Upvotes: 0

Views: 5665

Answers (1)

EpicPandaForce
EpicPandaForce

Reputation: 81529

The limitation is for createObjectFromJson() and createAllFromJson() methods, it has nothing to do with how GSON attempts to (or doesn't, in this case) deserialize it.

You can most likely define a type adapter for your GSON instance and it would fix the problem.

Gson gson = new GsonBuilder()
    .setExclusionStrategies(new ExclusionStrategy() {
        @Override
        public boolean shouldSkipField(FieldAttributes f) {
            return f.getDeclaringClass().equals(RealmObject.class); // is this still needed?
        }

        @Override
        public boolean shouldSkipClass(Class<?> clazz) {
            return false;
        }
    })
    .registerTypeAdapter(new TypeToken<RealmList<Integer>>() {}.getType(), new TypeAdapter<RealmList<Integer>>() {

        @Override
        public void write(JsonWriter out, RealmList<Integer> value) throws IOException {
            // Ignore for now
        }

        @Override
        public RealmList<Integer> read(JsonReader in) throws IOException {
            RealmList<Integer> list = new RealmList<Integer>();
            in.beginArray();
            while (in.hasNext()) {
                list.add(in.nextInt());
            }
            in.endArray();
            return list;
        }
    })
    .create();

Upvotes: 1

Related Questions