You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jackson如何将两个JSON字段反序列化为单个合并属性?

问题

我的MongoDB文档包含引用其他文档的结构,示例如下:

{ "_id": ..., "clientId": "foo123", "clientKind": "User", "otherProps": ... }

我需要将这类带有client...前缀的引用字段,转换为Java/Kotlin中的引用对象,比如:

new UserReference(id = "foo123")

或者泛型形式:

new Reference<User>(id = "foo123")

规则是:...Kind字段对应引用的类型(比如clientKind的值User对应User类型),...Id字段对应引用对象的id属性。希望通过Jackson自动完成这个转换,不需要自定义getter或处理私有属性,该怎么实现?

解决方案

方案1:自定义Jackson反序列化器(推荐)

通过自定义JsonDeserializer实现两个字段合并为一个引用对象的逻辑,步骤如下:

  1. 定义通用引用类(以Kotlin为例)
open class Reference<T>(val id: String)
class UserReference(id: String) : Reference<User>(id)
  1. 编写自定义反序列化器
    针对XxxId+XxxKind的字段对编写反序列化逻辑,匹配前缀并生成对应引用实例:
class ReferenceDeserializer : JsonDeserializer<Reference<*>>() {
    override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Reference<*> {
        val node = p.codec.readTree<JsonNode>(p)
        // 提取目标前缀(此处以"client"为例,可扩展为自动识别所有前缀)
        val prefix = "client"
        val id = node.get("${prefix}Id").asText()
        val kind = node.get("${prefix}Kind").asText()
        
        return when(kind) {
            "User" -> UserReference(id)
            // 可添加更多类型分支
            else -> throw IllegalArgumentException("不支持的引用类型: $kind")
        }
    }
}
  1. 在实体类中应用注解
    在需要转换的属性上添加反序列化器注解:
data class YourEntity(
    val _id: String,
    @JsonDeserialize(using = ReferenceDeserializer::class)
    val client: Reference<*>,
    val otherProps: Any
)

方案2:使用@JsonCreator结合构造器参数

无需额外编写反序列化器,直接通过实体类构造器接收两个字段并合并为引用对象:

data class YourEntity(
    val _id: String,
    val client: Reference<*>,
    val otherProps: Any
) {
    @JsonCreator
    constructor(
        @JsonProperty("_id") _id: String,
        @JsonProperty("clientId") clientId: String,
        @JsonProperty("clientKind") clientKind: String,
        @JsonProperty("otherProps") otherProps: Any
    ) : this(
        _id,
        when(clientKind) {
            "User" -> UserReference(clientId)
            else -> throw IllegalArgumentException("不支持的引用类型")
        },
        otherProps
    )
}

这种方式完全依托Jackson的构造器注入能力,不需要自定义getter或私有属性处理。

方案3:全局扩展BeanDeserializerModifier

如果需要批量处理多个实体类的这类字段转换,可以通过BeanDeserializerModifier扩展Jackson默认反序列化逻辑,自动识别XxxId+XxxKind字段并合并为引用属性。核心逻辑与自定义反序列化器一致,但能实现全局生效,无需逐个实体添加注解。

内容的提问来源于stack exchange,提问作者Ondra Žižka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:45:56