4

I have a json that holds a list of polymorphic objects,

{ 
  "someList": [
    { "type": "A", "value": {"aProp": false } },
    { "type": "B", "value": {"bProp": "1" } },
  ]
}

which represents a type hierarchy like this one:

sealed class Base
class A(val aProp: Boolean): Base()
class B(val aProp: String): Base()

class BaseList(val someList: List<Base>)

I would like to deserialize the JSON into such types,

but the default seales/polymorphic kotlinx serializer reads & writes the discriminator in the object itself, like this:

{ 
  "someList": [
    { "type": "A", "aProp": false },
    { "type": "B", "bProp": "1" }
  ]
}

while I got the discriminator outside of the object itself.

How can I deserialize such a JSON into this Kotlin type hierarchy?

Noam Freeman
  • 143
  • 1
  • 8

2 Answers2

1

If you don't want to write a custom serializer you have to match the structure of your JSON. Your original JSON represents an object inside an object, so you'll have to do something like:

data class A(val value: AValue): Base()

data class AValue(val aProp: Boolean)
gpunto
  • 2,573
  • 1
  • 14
  • 17
  • 1
    i think the `polymorphic` serializer will add the descriminator anyway. – Noam Freeman Dec 30 '21 at 20:39
  • I'm not sure what you mean. The `type` discriminator will be used to decide if the outer object is `A` or `B`. If you need it you can add it to the data class: `data class A(val type: String, val value: AValue): Base()` – gpunto Dec 31 '21 at 16:56
1

Good question! It annoys me so much there still isn't a standard for polymorphism in JSON.

I don't think writing a custom serializer is a desirable approach here. You'd have to apply custom serializers all over the codebase. Instead, you are probably better off introducing a pre- and postprocessing step wherever you serialize JSON. Thus intercept the JSON and convert it to a format supported by kotlinx.serialization.

Kotlinx serialization also supports "array polymorphism" in the JSON configuration, which I personally prefer but is much less common. It stores the type in the first element, and value in the second, of an array. This seems similar in intent to your target format. Using a JSON transformer it should be fairly trivial to covert all type and value objects to an array with two elements.

P s. I suggest you post about your use case as a feature request on GitHub. The maintainers are very receptive to feedback. It sounds like some type of strategy pattern to deal with different formats of polymorphism is in order.

Steven Jeuris
  • 18,274
  • 9
  • 70
  • 161