当前位置: 首页 > 知识库问答 >
问题:

如何使用jackson对Kotlin收藏进行反序列化

衡丰茂
2023-03-14

我想要的示例代码:

data class D(val a: String, val b: Int)
val jsonStr = """[{"a": "value1", "b": 1}, {"a": "value2", "b":"2}]"""
// what I need
val listOfD: List<D> = jacksonObjectMapper().whatMethodAndParameter?

共有3个答案

萧明贤
2023-03-14

如果您没有通用内容的类型,例如<代码>

val value = context.readValue<List<MyData>>(parser, valueType)

您不仅可以实现JsonSerialzier,还可以实现下面的代码示例中的ContextualDeserializer(基于Java中的这个答案):

class GenericListDeserializer : JsonDeserializer<List<*>>(), ContextualDeserializer {
    private var valueType: JavaType? = null

    override fun createContextual(ctxt: DeserializationContext, property: BeanProperty): JsonDeserializer<List<*>> {
        val wrapperType = property.type
        val valueType = wrapperType.containedType(0)
        val deserializer = GenericListDeserializer()
        deserializer.valueType = valueType
        return deserializer
    }

    override fun deserialize(parser: JsonParser, context: DeserializationContext): List<*> {
        val value :Any? = context.readValue(parser, valueType)
        return listOf(value)
    }
}
柳绪
2023-03-14

对于Jackson,按照jason minard的建议,简单地使用:

import com.fasterxml.jackson.module.kotlin.readValue

val listOfD: List<D> = jacksonMapper.readValue(jsonStr)

Kotlin wrt在反序列化集合方面没有什么特别之处,尽管您需要Kotlin jackson模块来反序列化没有注释的数据类。

也就是说,在您的情况下,它将需要完全具体化的类型信息,以便跟踪列表的泛型参数(D);否则(例如,如果您使用读取值(jsonStr,List::class.java),Jackson将只将其视为已擦除类型(即,Kotlin明确表示的)并将其反序列化为列表

将Jackson Java代码逐字翻译为Kotlin,从而实现了您想要的(正如@eski所评论的,请注意,您的示例中的JSON是无效的):

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

val jsonStr = """[{"a": "value1", "b": 1}, {"a": "value2", "b":2}]"""
val listOfD: List<D> = jacksonMapper.readValue(jsonStr, object : TypeReference<List<D>>(){})

assertEquals(listOf(D("value1", 1), D("value2", 2)), listOfD)

但这有点冗长和丑陋,因此可以将其隐藏在Kotlin(扩展)函数中(特别是如果您计划多次使用它):

inline fun <reified T> ObjectMapper.readValue(json: String): T = readValue(json, object : TypeReference<T>(){})

这样你就可以直接打电话:

val listOfD: List<D> = jacksonMapper.readValue(jsonStr)

这就是jackson Kotlin模块中包含的内容。

益楷
2023-03-14

使用Jackson静态编程语言模块当前版本,如果您导入完整的模块包或特定的扩展功能,您将拥有所有可用的扩展方法。例如:

import com.fasterxml.jackson.module.kotlin.*  
val JSON = jacksonObjectMapper()  // keep around and re-use
val myList: List<String> = JSON.readValue("""["a","b","c"]""")

因此,Kotlin的Jackson模块将推断正确的类型,您不需要类型引用实例。

因此,您的案例(稍微重命名并修复了数据类和JSON):

import com.fasterxml.jackson.module.kotlin.readValue

data class MyData(val a: String, val b: Int)
val JSON = jacksonObjectMapper()  

val jsonStr = """[{"a": "value1", "b": 1}, {"a": "value2", "b": 2}]"""
val myList: List<MyData> = JSON.readValue(jsonStr)

您也可以使用以下表格:

val myList = JSON.readValue<List<MyData>>(jsonStr)

如果没有导入,则会出现错误,因为找不到扩展函数。

 类似资料:
  • 来自REST服务的json对象 使用JacksonInFiveMinutes中的代码 ObjectMapper mapper=new ObjectMapper(); Map userData=mapper.read值(webResource.queryParams(queryParams). get(String.class);, Map.class); 在哪里: 从REST服务返回json 从J

  • 问题内容: 我使用杰克逊测试了Scala案例类的序列化。 DeserializeTest.java 福斯卡拉 当我运行上述Java类时,抛出了一个异常: 我如何(反)序列化Scala案例类? 问题答案: Jackson希望您的类是JavaBean,这意味着它希望该类的每个属性都具有getX()和/或setX()。 选项1 您可以使用注释BeanProperty在Scala中创建JavaBean类。

  • 问题内容: 我整天都在寻找可以解决这个问题的东西,但是到目前为止我还没有碰到很多运气。 我的问题很简单:如何使用Jackson正确反序列化匿名对象。 在出现异常之前,此输出为:JSON = [“ com.foo.test.JacksonTest $ 1”,{“ value”:5}]: 线程“主”中的异常com.fasterxml.jackson.databind.JsonMappingExcept

  • 问题内容: 我有一些类A,B,C,它们都继承自BaseClass类。 我有一个String json,其中包含A,B,C或BaseClass的json表示形式。 我想要某种方法将此字符串反序列化为BaseClass(多态反序列化)。像这样 可以是A,B,C或BaseClass中任何一个的Json String表示形式。 问题答案: 目前尚不清楚原始海报有什么问题。我猜这是两件事之一: 未绑定JSO

  • 我有一个类,它可以很好地序列化和反序列化: 我还有一个< code>PacketResponse对象,类似于: 对象的序列化工作正常,结果如下: 然而,当我试图将这个JSON反序列化回一个< code>PacketResponse对象时,使用 我得到一个。 似乎它正在尝试反序列化 ,但由于它没有直接执行此操作,杰克逊看不到 注释,而是正在寻找 字段(因为这是构建器方法的名称)。 有人能帮我找出反序

  • 我试图通过Kotlin使用Jackson对lastfm api提供的xml进行反序列化。我用JAXB在Java中实现了这一点,我正在尝试移植它。除以下示例中的“未包装列表”字段外,所有功能都正常工作。我知道Track数据类正在工作,因为如果我使用而不是