2

I want to convert JSON string into objects and I'm trying to find the best way to do that since those objects are really similar and the only change is the "data" field between them:

{
  "event_type": "REGISTER",
  "day": "2021-01-01",
  "data": {
    "name": "Kyore",
    "age": 10
  }
}

{
  "event_type": "DELETE",
  "day": "2021-01-01",
  "data": {
    "id": "1234-1234-1234",
    "reason": "user requested"
  }
}

Those events come from a SQS Listener as a JSON string and I'm trying to find the best way to handle them with Kotlin, but I'm not sure how to pick which class will be the one to be converted in my listener:

abstract class Event {
    abstract val event_type: String
    abstract val day: String
    abstract val data: EventData

    abstract class EventData
}

class RegisterEvent(
    override val eventType: String,
    override val day: String,
    override val data: RegisterData
) : Event() {

    data class RegisterData(
        val name: String,
        val age: Int
    ) : Event.EventData()
}

class DeleteEvent(
    override val eventType: String,
    override val day: String,
    override val data: DeleteData
) : Event() {

    data class RegisterData(
        val id: String,
        val reason: String
    ) : Event.EventData()
}

What is the best way to convert the message string in the correct event?

Kyore
  • 388
  • 2
  • 7
  • 29
  • 1
    What you are trying to do is called [polymorphic deserialization](https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/polymorphism.md). It requires target classes of deserialization to have a common superclass (preferrably sealed). Read this thread: https://stackoverflow.com/a/64537173/421195 – paulsm4 Jul 12 '21 at 18:45
  • Looks like I'm in the correct way, but I don't get how I will tell Jackson which one of my classes should be used in the deserialization. – Kyore Jul 12 '21 at 20:29
  • 1
    So I guess you didn't read far enough to get to the part where it says " You will have to write custom JsonContentPolymorphicSerializer and wire it to Decomposed class; also you have to write custom serializer for StringValue class". PS: I use Java (not Kotlin), so I really can't advise you on Kotlin particulars. PPS: "Kotlin" reminds me of the German word [kotzen](https://m.interglot.com/de/en/kotzen) – paulsm4 Jul 13 '21 at 01:08

1 Answers1

1

After a while reading about Polymorphic Deserialization, I found a solution to that using Kotlin and Jackson, which basically we need to use the @JsonTypeInfo and @JsonSubTypes from jackson's annotations and tell it which property will be checked to deserialize and which Class should be used when it match, using the OP example:

data class Event(
   val event_type: String,
   val day: String,
   val data: EventData
) {

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "event_type", include = JsonTypeInfo.As.EXTERNAL_PROPERTY)
    @JsonSubTypes(value = [
        JsonSubTypes.Type(RegisterData::class, name = "REGISTER"),
        JsonSubTypes.Type(DeleteData::class, name = "DELETE")
    ])
   abstract class EventData
}

data class RegisterData(
    val name: String,
    val age: Int
) : Event.EventData()

data class DeleteData(
    val id: String,
    val reason: String
) : Event.EventData()

So when we convert the JSON string into the Event object, the data property will be mapped with one of the RegisterData and DeleteData classes.

Kyore
  • 388
  • 2
  • 7
  • 29