【问题标题】:Replace URL fields by Uri with Jackson用 Jackson 替换 Uri 的 URL 字段
【发布时间】:2020-03-06 11:01:18
【问题描述】:

我在字段中有一些带有 URL 的对象,例如:

class A {

    val url1 : URL
    val url2 : URL
    val urls : ArrayList<URL>

}

我想用 Uri 替换 URL,但我使用 Jackson 和 SQLite 来序列化对象并将它们存储在 DB 中。因此,如果我更改类型,我将无法检索存储的对象。

所以,我已经实现了这样的自定义反序列化:

class UriDeserializer : StdDeserializer<Uri>(Uri::class.java) {

    override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): Uri {

        return Uri.parse(p?.valueAsString)
    }

}

class UriArrayDeserializer : StdDeserializer<ArrayList<Uri>>(ArrayList::class.java) {

    override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): ArrayList<Uri> {

        val uriArray = arrayListOf<Uri>()

        p?.nextToken()
        while (p?.currentToken != JsonToken.END_ARRAY) {

            val uri = Uri.parse(p?.text)
            uriArray.add(uri)

            p?.nextToken()
        }

        return uriArray
    }


}

然后我为班级中的字段添加了 UriDeserializer:

class A {

    @JsonDeserialize(using = UriDeserializer::class)
    val url1 : Uri

    @JsonDeserialize(using = UriDeserializer::class)
    val url2 : Uri

    @JsonDeserialize(using = UriArrayDeserializer::class)
    val urls : ArrayList<Uri>

}

使用此代码,我可以反序列化我的旧对象,但现在我无法序列化新对象,我收到此错误:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: com.package.A["url2"]->android.net.Uri$StringUri["canonicalUri"])

我是否也必须实现自定义序列化?也许有一种最简单的方法可以用 Uri 替换 URL ?

解决方案

感谢检查的答案,我找到了问题的解决方案:所以我使用了带有自定义序列化器和反序列化器的 MixIn 接口。

@JsonSerialize(using = UriSerializer::class)
@JsonDeserialize(using = UriDeserializer::class)
interface UriMixIn

class UriDeserializer : StdDeserializer<Uri>(Uri::class.java) {

    override fun deserialize(p: JsonParser?, ctxt: DeserializationContext?): Uri {
        return Uri.parse(p?.valueAsString)
    }
}

class UriSerializer : StdSerializer<Uri>(Uri::class.java) {

    override fun serialize(value: Uri?, gen: JsonGenerator?, provider: SerializerProvider?) {
        gen?.writeString(value?.toString())
    }
}

然后,我在需要的地方添加了 UriMixIn:

val jackson = jacksonObjectMapper()
jackson.addMixIn(Uri::class.java, UriMixIn::class.java)

这个解决方案就像一个魅力!非常感谢您的帮助,祝您有美好的一天!

【问题讨论】:

    标签: java android kotlin jackson


    【解决方案1】:

    您可以实现自定义序列化器或使用MixIn 功能。

    要了解原因,我们需要看看android.net.Uri 类是如何实现的。我们可以通过Android Googlesource查看来源。快速查看,我们注意到parse 方法返回StringUri 对象:

    public static Uri parse(String uriString) {
        return new StringUri(uriString);
    }
    

    内部文档中提到:

    本课程旨在尽量减少前期工作。到 完成 也就是说,我们根据用户传入的内容来改变实现。 例如,如果用户传入一个 URI 字符串 (StringUri) 和另一个如果用户传入 单个组件 (OpaqueUri)

    让我们进一步分析。 StringUriprivate static class,它看起来不像普通的 POJO。另一方面,如果Uri 是从String 构建的,则有问题的canonicalUri 字段返回this,因此这是我们需要自定义序列化程序或使用MixIn Feature 的原因,我们可以忽略此@987654345 @。

    Jackson 用于serialise 而不是常规POJO 对象时,这是一个非常常见的问题。类似的问题:

    1. Why Jackson JSON mapping exception when Serializing/Deserializing Geometry type
    2. Serializing/deserializing exceptions without stack trace using Jackson
    3. Is there a built in mechanism within org.kohsuke.github to serialize GHRepository objects to JSON?
    4. Jackson/Gson serialize and deserialize JavaFX Properties to json
    5. Java InvalidDefinitionException when serializing object with jackson databind

    一些例子,如何使用MixIn

    1. Make Jackson serializer override specific ignored fields
    2. Custom Jackson Serializer for a specific type in a particular class
    3. What is equivalent code settings for @JSonIgnore annotation?
    4. Jackson parse json with unwraping root, but without ability to set @JsonRootName

    另外,您可以使用MixIn 功能为Uri 类型全局注册serialiser/deserialiser。在这种情况下,您不需要实现UriArrayDeserializer 类。

    见:

    1. Jackson – Custom Serializer

    【讨论】:

    • 非常感谢您的回答和您的宝贵时间!如果我理解正确,我可以制作一个自定义序列化器和一个自定义反序列化器,然后我在 MixIn 接口中同时使用这两者,然后我的jacksonObjectMapper 可以序列化/反序列化我所有的Uri,包括array
    • @Ady,是的。这是正确的。您需要全局注册序列化器和反序列化器。您可以通过使用MixIn 并在类型级别上注册它们或在ObjectMapper 级别上注册来做到这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-11
    • 2018-07-09
    • 2013-02-10
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多