Hi everybody. May be someone is familiar with chan...
# serialization
s
Hi everybody. May be someone is familiar with changes around Kotlin's 'object' (and may be sealed classes) made between 1.3.50 and 1.4.30 ? I missed that and cannot find in changelog anything related. Following code works quite different on these versions:
Copy code
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
sealed class A {
    @JsonTypeName("B")
    object B: A()
    @JsonTypeName("C")
    object C: A()
    @JsonTypeName("D")
    data class D(val i: Int): A()
}

class JsonTest {
    private val objectMapper = jacksonObjectMapper().apply(configureObjectMapper)
    private fun <T> parse(str: String, clazz: Class<T>): T = objectMapper.readValue(str, clazz)
    private fun <T> stringify(value: T): String = objectMapper.writeValueAsString(value)

    @Test
    fun testPatternMatching() {
        val x1 = A.B
        val x2 = parse(stringify(x1), A::class.java)
        val x3 = A.C

        listOf(x1,x2,x3).forEach {
            when(it) {
                A.B -> println("b ${it as Any}")
                A.C -> println("c ${it as Any}")
                is A.D -> println("d ${it as Any}")
                else -> println("? ${it as Any}")
            }
        }
        assertEquals(A.B, x1)
        assertEquals(A.B, x2) // <--- failed assertion in 1.4.30
        assertEquals(x1, x2)
    }
}
In 1.3.50 projects, it prints:
Copy code
b com.example.A$B@184a254d
b com.example.A$B@184a254d
c com.example.A$C@41443428
In 1.4.30 (and 1.5.x) projects, it prints:
Copy code
b com.example.A$B@12a1cc8d
  ? com.example.A$B@7b2edf94
  c com.example.A$C@73baae4e
and test fails with
Copy code
expected:<com.example.A$B@12a1cc8d> but was:<com.example.A$B@7b2edf94>
As I can see - after serialization/deserialation I got 2nd A.B object (nonsense for a singleton). This code can be fixed by writting 'is A.B', in that case both instances (x1 and x2) will be matched. But who knows what is going on here and why it changed since 1.4.x ?
e
Since you're using Jackson, you're operating in the JVM-world, where an object is just a singleton class.. (and other nice things might happen, such as null values being set on a non-nullable property through reflection) I would update jackson and see if it fixes things.. This channel in general is related to
kotlinx.serialization
s
Well, I understand about JVM-world. But what change between 1.3 and 1.4 affects this behavior ? If it was intentional why not to throw warnings about such matching (hei, may be you want to use 'is' even for object) cases? Why it works in 1.3 ?
e
your jackson version correctly identifies and uses the singleton instance in 1.3.x. you probably need to upgrade to a newer jackson version compatible with 1.4.x
what jackson version are you using?
s
In 1.3.x project:
Copy code
jackson_version=2.10.2
In 1.4.x project:
Copy code
jackson_version=2.12.1
What version you can suggest as 'compatible with 1.4' ?
e
Initial 1.4 support came in 2.12.0, but might be this issue you're facing is fixed in a later patch version. Why not try 2.12.5? 🙂
s
Just tried, same result. Especially cynic warning from Kotlin compiler 🙂 about 'else is not required here'
could be related to your issue
s
@Emil Kantis Thanks a lot, will read. Also would like to test same with kotlin serialization.
Yeah, just did same test for kotlin serialization, and works in 1.4.30 as expected. So it's only issue with Jackson.
e
#serialization is about kotlinx.serialization, this should be in #jackson-kotlin.
👍 1
s
@Emil Kantis One more time - thanks for your time, I found where I was wrong and solved the issue. Just in case someone has same issue: I used helper method from jackson-module-kotlin:
Copy code
fun jacksonObjectMapper(): ObjectMapper = jsonMapper { addModule(kotlinModule()) }
but it leads to using wrong (default setting) for kotlin singletons. Correct usage will be:
Copy code
KotlinModule(singletonSupport = SingletonSupport.CANONICALIZE)
@ephemient thanks for pointing out, I didn't found that channel at first time.