Как написать собственный десериализатор Джексона в котлине для Arrow's Option? - PullRequest
0 голосов
/ 06 октября 2019

Мне нужно десериализовать необязательные значения из 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 ":" Some content "}";строка: 2, столбец: 3] com.fasterxml.jackson.databind.exc.InvalidDefinitionException: невозможно создать экземпляр $Sample (не существует создателей, как, например, конструкция по умолчанию): невозможно десериализовать из значения объекта (без делегата или свойства). на основе создателя) в [Source: (String) "{" id ":" 1 "," content ":" Некоторый контент "}";строка: 2, столбец: 3] в com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from (InvalidDefinitionException.java:67) в com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition (DeserializationContext.java:1).fasterxml.jackson. .deserializeFromObject (BeanDeserializer.java:326) при com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize (BeanDeserializer.java:159) при com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose (ObjectMapper.java:4013) вcom.fasterxml.jackson.databind.ObjectMapper.readValue (ObjectMapper.java:3004)

Как заставить Джексона работать с типом Option из arrow-kt?

...