简体   繁体   English

Jackson 自定义序列化程序简化

[英]Jackson Custom Serializer simplification

I have a payload like this:我有这样的有效载荷:

items: [
{
   "foo" : "baz",
   "whatever" : "thing"
}
]

Literally, all I have to do is just navigate to /items/0 and then continue the normal deserialization process.从字面上看,我所要做的就是导航到/items/0 ,然后继续正常的反序列化过程。 But I don't see how I can do that with the current JsonDeserializer.但是我不知道如何使用当前的 JsonDeserializer 来做到这一点。


class BugDeserializer : JsonDeserializer<Bug>() {
    override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): Bug {
        val node: TreeNode = p!!.readValueAsTree()

        val correct = node.at("/items/0")
        
        // Now what? 'correct' has no `readValueAs` method
        return p.readValueAs(Bug::class.java)

    }
}

Once I navigate properly, I don't see anyway to thus "continue".一旦我正确导航,无论如何我都看不到“继续”。 I have gone so far as to instantiate another ObjectMapper to do the job, but this doesn't work either because I have the deserializer directly on my Bug class, so it gets invoked twice.我什至实例化了另一个ObjectMapper来完成这项工作,但这也不起作用,因为我直接在我的Bug class 上安装了反序列化器,所以它被调用了两次。

How do I simply deserialize normally, once I've navigated to the correct json path?一旦我导航到正确的 json 路径,我该如何简单地正常反序列化?

If you have an input {"items": [{"foo": "baz","whatever": "thing"}]} json file and you want to deserialize it to a Bug list where Bug class is like data class Bug(var foo: String, var whatever: String) you can use TypeReference to instantiate reference to the generic type List<Bug> like below:如果你有一个输入{"items": [{"foo": "baz","whatever": "thing"}]} json 文件,你想将它反序列化到一个Bug列表,其中Bug class 就像data class Bug(var foo: String, var whatever: String)您可以使用TypeReference来实例化对泛型类型List<Bug>的引用,如下所示:

data class Bug(var foo: String, var whatever: String)

fun main() {
    val mapper = ObjectMapper().registerKotlinModule()
    val json = """
       {"items": [
        {
           "foo" : "baz",
           "whatever" : "thing"
        }
        ]}
    """.trimIndent()

    val items: JsonNode = mapper.readTree(json).get("items")
    val bugs: List<Bug> = mapper.convertValue(items, object: TypeReference<List<Bug>>(){})
}

To override custom deserialiser and provide your own you need to use BeanDeserializerModifier .要覆盖自定义反序列化器并提供您自己的反序列化器,您需要使用BeanDeserializerModifier You can find example here:你可以在这里找到例子:

Also you can implement a new custom deserialiser, skip the beginning of JSON payload, deserialise to an inner class and return what you want.您还可以实现一个新的自定义反序列化器,跳过JSON有效负载的开头,反序列化为内部 class 并返回您想要的内容。 It could look like below:它可能如下所示:

import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JavaType
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.type.SimpleType

class BugJsonDeserializer : JsonDeserializer<Bug>() {

    private val innerBugType: JavaType = SimpleType.constructUnsafe(InnerBug::class.java)

    override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Bug {
        p.nextToken() // start object
        p.nextToken() // field name
        p.nextToken() // start array

        val innerDeser: JsonDeserializer<*> = ctxt.findNonContextualValueDeserializer(innerBugType)
        val (foo, whatever) = innerDeser.deserialize(p, ctxt) as InnerBug

        return Bug(foo, whatever)
    }

    private data class InnerBug(
        val foo: String? = null,
        val whatever: String? = null
    )
}

You need to register above deserializer:您需要在反序列化器上方注册:

@JsonDeserialize(using = BugJsonDeserializer::class)
data class Bug(
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM