杰克逊·科特林反序列化使用自定义序列化程序失败

时间:2019-08-26 21:07:13

标签: json kotlin jackson

这是我的代码:

class Foo<K>(
    val foo: Bar<K>
)

class Bar<K>(
    val bar: K
)

class Baz(
    val baz: ByteArray
)

internal class BazSerializer : JsonSerializer<Baz>() {
    override fun serialize(value: Baz, gen: JsonGenerator, serializers: SerializerProvider) {
        gen.writeString(String(value.baz))
    }
}

internal class BazDeserializer : JsonDeserializer<Baz>() {
    override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Baz {
        return Baz(p.valueAsString.toByteArray())
    }
}

val MAPPER = ObjectMapper()
    .registerModule(
        SimpleModule()
            .addSerializer(Baz::class.java, BazSerializer())
            .addDeserializer(Baz::class.java, BazDeserializer())
    ).registerKotlinModule()
}

我的自定义解串器/序列化器仅用于字节->字符串转换,因此可以在JSON中很好地显示。这是我的绿色测试:

@Test
fun `foo bar`() {
    val type1 = "text"
    val type2 = Baz("baz".toByteArray())

    val fooStringOriginal = Foo(Bar(type1))
    val fooByteArrayOriginal = Foo(Bar(type2))

    // {"foo":{"bar":"text"}}
    val s1 = MAPPER.writeValueAsString(fooStringOriginal)
    // {"foo":{"bar":"baz"}}
    val s2 = MAPPER.writeValueAsString(fooByteArrayOriginal)

    val fooStringDeser = MAPPER.readValue<Foo<String>>(s1)
    val fooByteArrayDeser = MAPPER.readValue<Foo<Baz>>(s2)

    // {"foo":{"bar":"text"}}
    val s11 = MAPPER.writeValueAsString(fooStringDeser)
    // {"foo":{"bar":"baz"}}
    val s21 = MAPPER.writeValueAsString(fooByteArrayDeser)

    assertEquals(s1, s11)
    assertEquals(s2, s21)
    assertEquals(fooStringOriginal.foo.bar, fooStringDeser.foo.bar)
    assertEquals(String(fooByteArrayDeser.foo.bar.baz), "baz")
    assertTrue(fooByteArrayDeser.foo.bar is Baz)
}

现在让我们说,不是要在我的api上公开MAPPER对象,而是要向kt文件中添加序列化和反序列化方法,并在测试中使用这些方法:

fun <K> serialize(mapping: Foo<K>): String {
    return MAPPER.writeValueAsString(mapping)
}

fun <K> deserialize(json: String): Foo<K> {
    return MAPPER.readValue<Foo<K>>(json)
}

但是由于某种原因,kotlin没有收到我的Baz,并认为这是HashMap

@Test
fun `failing foo bar`() {
    val type1 = "text"
    val type2 = Baz("baz".toByteArray())

    val fooStringOriginal = Foo(Bar(type1))
    val fooByteArrayOriginal = Foo(Bar(type2))

    val s1 = serialize(fooStringOriginal)
    val s2 = serialize(fooByteArrayOriginal)

    val fooStringDeser = deserialize<String>(s1)
    val fooByteArrayDeser = deserialize<Baz>(s2)

    val s11 = serialize(fooStringDeser)
    val s21 = serialize(fooByteArrayDeser)

    assertEquals(s1, s11)
    assertEquals(s2, s21)
    assertEquals(fooStringOriginal.foo.bar, fooStringDeser.foo.bar)
    assertEquals(String(fooByteArrayDeser.foo.bar.baz), "baz")
    // ^^^^^ ERROR: java.lang.ClassCastException: java.lang.String cannot be cast to Baz
    assertTrue(fooByteArrayDeser.foo.bar is Baz)
}

有人知道MAPPER.readValue<Foo<Baz>>为何有效而deserialize<Baz>无效(只是返回MAPPER.readValue<Foo<K>>)的线索吗?

编辑:我不能使用内联修饰符,因为我希望从Java中调用它。

0 个答案:

没有答案