Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: Jackson deserialization of inline classes

Lets say i have

inline class CustomId(val id: String)

And i use Jackson to deserialize it back to a object, Jackson throws an Exception:

InvalidDefinitionException
Cannot construct instance of CustomId (no Creators, like default construct, exist)

How to solve this Problem?
How can I create a custom deserializer?

like image 378
Dachstein Avatar asked May 31 '19 11:05

Dachstein


1 Answers

Say I have a payment like follows

@JvmInline
value class PaymentMethod(val method: String)

data class Payment(val Method: PaymentMethod)

data class PaymentDto(val method: PaymentMethod) {
    companion object {
        @JvmStatic
        @JsonCreator
        fun create(method: String) = PaymentDto(PaymentMethod(method))
    }
}

The inline class or value class on the JVM would be serialized as a string. In order to deserialize this as an inline class you can use @JsonCreator. The following two tests show that the value is correctly deserialized back as a wrapper

@Test
fun `should send wrapper as string`() {
    val objectMapper = jacksonObjectMapper().findAndRegisterModules()
    val payment = Payment(PaymentMethod("PAYPAL"))
    val expectedJson = """{"method":"PAYPAL"}"""

    val json = objectMapper.writeValueAsString(payment)

    assertNotNull(json)
    assertEquals(expectedJson, json)
}

@Test
fun `should deserialize string as inline class`() {
    val objectMapper = jacksonObjectMapper().findAndRegisterModules()
    val payment = Payment(PaymentMethod("PAYPAL"))
    val json = objectMapper.writeValueAsString(payment)

    val result =  assertDoesNotThrow { objectMapper.readValue<PaymentDto>(json) }

    assertNotNull(result)
    assertEquals(result.method.method, "PAYPAL")
}
like image 172
Daniel Jacob Avatar answered Oct 24 '22 09:10

Daniel Jacob