2

With polymorphic serialization, I want to serialize classes A, B1, B2. I want to get the following line with class B2

{"type":"type_2","baseField":"base_field_B","fieldB":true,"fieldB2":"field_B_2"}

I use hierarchy like

interface BaseClass {
    val baseField: String
}

@Serializable
@SerialName("type_1")
data class A(
    override val baseField: String,
    val fieldA: Int
) : BaseClass

@Serializable
@SerialName("type_2")
abstract class B: BaseClass{
    abstract override val baseField: String
    abstract val fieldB: Boolean
}

@Serializable
data class B1(
    override val baseField: String,
    override val fieldB: Boolean,
    val fieldB1: Float
) : B()

@Serializable
data class B2(
    override val baseField: String,
    override val fieldB: Boolean,
    val fieldB2: String
) : B()

and doing serialization like this

Json(context = SerializersModule {
    polymorphic(BaseClass::class) {
        A::class with A.serializer()
        B::class with B.serializer()
    }
}).stringify(
    PolymorphicSerializer(BaseClass::class),
    B1("base_field_B", true, "field_B_2")
)

As a result, I get kotlinx.serialization.SerializationException: class B2 (Kotlin reflection is not available) is not registered for polymorphic serialization in the scope of interface BaseClass (Kotlin reflection is not available)

How do I serialize a given structure correctly? Classes B1, B2 must be serialized with type "type_2".

1 Answers1

0

for what you want ... maybe optional String and Float fields would suffice as a workaround to merge B, B1 and B2 into one class?

@Serializable
@SerialName("type_2")
data class B(
    override val baseField: String,
    val fieldB: Boolean,
    val fieldB1: Float? = null,
    val fieldB2: String? = null
): BaseClass

As far as the Serializer is concerned you have not registered B1 and B2 and you cannot use the same type "type_2" since deserialization will be impossible, it is not smart enough to use a presence or absence of keys to patternmatch the right serializer to serialize and deserialize to the correct type they need to have a different type value on each type (A, B, B1, B2) and all need to be serialized

Nikky
  • 498
  • 2
  • 9
  • 1
    Thanks for the answer. But i think combining B1 and B2 in one object with optional fields is not the best option. I do not want to give colleagues the opportunity to make a mistake when creating an object (For example, B2 with empty fields fieldB1 and fieldB2, or B2 with empty fieldB2 and filled fieldB1). B2 should not have extra fields that relate to B1. – Est Stalegaykin Oct 22 '19 at 10:51
  • in that case they cannot be the same class and they cannot use the same `"type": "type_2"` for serialization. - Another option is to use a merged form for serialization and then provide extension functions to convert to the other types and back. - There is also the option that you roll your own deserialization that somehow matches by existence of keys on the object which serializer to use, but this is hard – Nikky Oct 23 '19 at 20:05