[SOLVED] Deserializing a generic type using gson in kotlin – Stack Overflow

Question

This Content is from Stack Overflow. Question asked by user3148156

I have a generic type Animal implemented as a sealed class that can be a Dog or a Cat.

sealed class Animal(val typeOfAnimal: String) {
  data class Dog(val barkVolume: Int): Animal("dog")
  data class Cat(val hasStripes: Boolean): Animal("cat")
}

According to http://jansipke.nl/serialize-and-deserialize-a-list-of-polymorphic-objects-with-gson/ you can deserialize an Animal by registering a RuntimeTypeAdapterFactory

val animalAdapterFactory = RuntimeTypeAdapterFactory.of(Animal::class.java, "typeOfAnimal").registerSubtype(Dog::class.java, Dog::class.java.qualifiedName).registerSubtype(Cat::class.java, Cat::class.java.qualifiedName)
gson = GsonBuilder().registerTypeAdapterFactory(animalAdapterFactory)

But if I try to deserialize an animal that looks like

jsonStr = "{barkVolume: 100}"
gson.fromJson(json, Animal::class.java)

RuntimeTypeAdapterFactory complains that it can’t deserialize Animal as it does not dfine a field named “typeOfAnimal”

To my understanding typeOfAnimal is a field you add to differentiate the subtypes and not something you need in the json you are deserializing. Because my json is really coming from an api I cannot add the field.



Solution

typeOfAnimal is required because gson must know which class should choose to deserialize your json. There is no way to guess the type, but you can implement your own deserializator. In a custom deserializator you can implement logic such as:

if (jsonObject.get("barkVolume") != null) {
    // retun Dog object
}


This Question was asked in StackOverflow by user3148156 and Answered by Mateusz It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?