Hello. I have a question about polymorphic seriali...
# serialization
z
Hello. I have a question about polymorphic serialization for inner objects of a base json object. For example i have an object like this:
Copy code
{
  "cars": []
}
Let’s name it just Base. Next i have a base class for cars. Just Car class. And two subclasses. Truck and Tesla.
Copy code
@Serializable
open class Car {
    @SerialName("ms")
    protected val maxSpeed: Int = 0
}

@Serializable
class Truck(
    @SerialName("lc")
    private val loadCapacity: Int = 0,
    
    @SerialName("ft")
    private val fuelType: String = ""
): Car()

@Serializable
class Tesla(
    @SerialName("rt")
    private val rechargeTime: Int = 0
): Car()
As you see these two subclasses have different properties. Let’s add some cars to the array of the base class:
Copy code
{ 
  "cars": [{ ms: 80, lc: 1000, ft: "diesel" }, { ms: 180, rt: 4 }]
}
And now i want to transform this json object into Base class.
Copy code
class Base {
    val cars = listOf<Car>()
}
I know there is a polymorphic serializers module that allows me to register a hierarchy of classes. Maybe i need to do something like this: Register a hierarchy of classes.
Copy code
val json = Json {
    serializersModule = SerializersModule {
        polymorphic(Car::class) {
            subclass(Truck::class)
            subclass(Tesla::class)
        }
    }
}
Add an information about types into the json
Copy code
{ 
  "cars": [{ type: "truck", ms: 80, lc: 1000, ft: "diesel" }, { type: "tesla", ms: 180, rt: 4 }]
}

@Serializable
@SerialName("truck")
class Truck(
    @SerialName("lc")
    private val loadCapacity: Int = 0,

    @SerialName("ft")
    private val fuelType: String = ""
): Car()

@Serializable
@SerialName("tesla")
class Tesla(
    @SerialName("rt")
    private val rechargeTime: Int = 0
): Car()
And then just transform a string into the base class.
Copy code
json.decodeFromString<Base>(string)
But this is not working. I see that Base class is not in the hierarchy so it can not be achieved by this way.
a
But this is not working
Can you say more about what's not working? Is there an error, or does the decoded data not match in some way?
a
you have to mark all the classes with
@Serializable
z
Guys, sorry for this misunderstanding. The
Car
class is not abstract, it is open. Subclasses and the
Car
class already marked as
@Serializable
The error i am getting is
Unexpected JSON token at offset 11: Encountered an unknown key 'type' at path
So if the
Car
class is abstract there is no problems. Everything works fine. But in my case the class is open. My question is only about how to achieve this with a base class marked as open.
d
Your
Car
class is the issue. It needs to be abstract and
maxSpeed
needs to be abstract
g
I think you could add a
CarInterface
, Car will inherit this interface, and then your configuration becomes:
Copy code
val json = Json {
    serializersModule = SerializersModule {
        polymorphic(CarInterface::class) {
            subclass(Truck::class)
            subclass(Car::class)
            subclass(Tesla::class)
        }
    }
}
Because if Car is open, it means it can be instantiated, so it's another possibility of the polymorphism (even if the naming is questionnable in this case).
👍 1
1