0

我需要将 json 中的可选值反序列化为 Kotlin 中具有Option类型的数据类。例子:

data class Sample(val id: Long, val content: Option<String>)

fun main() {
  val mapper = ObjectMapper()
  val v1 = mapper.readValue("""
  { "id": "1", "content": null }
  """.trimIndent(), Sample::class.java)


  val v2 = mapper.readValue("""
  { "id": "2", "content": "Some content" }
  """.trimIndent(), Sample::class.java)

  assert(v1.id == 1)
  assert(v1.content == Option.empty())
  assert(v2.id == 2)
  assert(v2.content == Option.just("Some content"))
}

我正在努力为这个用例编写正确版本的反序列化器。这是我尝试过的:

class OptionDeserializer<T>(private val clazz: Class<T>) : StdDeserializer<Option<T>>(clazz) {

  override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): Option<T> {
      val value = p?.codec?.readValue(p, clazz)
      return if (value == null) Option.empty() else Option.just(value)
  }
}

fun main() {
  val mapper = ObjectMapper()
  val module = SimpleModule("Option")
  module.addDeserializer(Option::class.java, 
    OptionDeserializer(Option::class.java))
  mapper.registerModule(module)

  val v1 = mapper.readValue("""
  { "id": "1", "content": "Some content" }
  """.trimIndent(), Sample::class.java)

  assert(v1.id == 1)
  assert(v1.content == Option.just("Some content"))
}

但这不起作用并引发错误:

无法构造实例$Sample(没有创建者,如默认构造,存在):无法从 [Source: (String)"{ "id" : "1", "content" : "部分内容" }"; 行:2,列:3] com.fasterxml.jackson.databind.exc.InvalidDefinitionException:无法构造实例$Sample(不存在像默认构造一样的创建者):无法从 [Source: (String)"{ "id" : "1", "content" : "Some content “}”;line: 2, column: 3] at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1452) at com .fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1028) 在 com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297) 在 com.fasterxml.jackson.databind.deser.BeanDeserializer .

如何让杰克逊使用Option来自的类型arrow-kt

4

2 回答 2

1

您需要注册 Kotlin 模块

val mapper = ObjectMapper().registerModule(KotlinModule())

这是 Maven 依赖项,以防您还没有它。

于 2020-02-12T23:05:05.570 回答
0

另一种选择是使用自定义序列化程序。在这种情况下,无需显式注册任何内容。请参阅此处的建议用法。

于 2021-08-16T17:31:25.613 回答