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

求助:Kotlin委托属性Jackson反序列化失败的解决办法

解决Kotlin委托属性数据类的Jackson反序列化问题

问题核心在于:Jackson默认会尝试寻找与ExtendedResponseDto构造参数base对应的JSON字段,但你的JSON结构里并没有名为base的嵌套对象,而是把name/age和city平级放置,导致无法匹配非空的base参数,抛出缺失参数异常。

简便解决方案:自定义带@JsonCreator的构造函数

通过手动指定构造函数的参数映射,让Jackson知道如何从平级的JSON字段中构建base委托对象和当前类的额外字段:

@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION, defaultImpl = BaseResponseDto::class)
interface ResponseDto {
    val name: String
    val age: Int
}

data class BaseResponseDto(
    override val name: String,
    override val age: Int,
) : ResponseDto

data class ExtendedResponseDto(
    private val base: ResponseDto,
    val city: String,
) : ResponseDto by base {
    // 自定义构造函数,用于Jackson反序列化
    @JsonCreator
    constructor(
        @JsonProperty("name") name: String,
        @JsonProperty("age") age: Int,
        @JsonProperty("city") city: String
    ) : this(BaseResponseDto(name, age), city)
}

// 测试代码
val json = """{
    "name": "Thomas",
    "age": 3,
    "city": "Paris"
}"""

val mapper = jacksonObjectMapper()
val dto = mapper.readValue<ExtendedResponseDto>(json)
println(dto.name) // 输出 Thomas
println(dto.age)  // 输出 3
println(dto.city) // 输出 Paris

为什么@JsonUnwrapped不生效?

@JsonUnwrapped主要用于将嵌套对象的字段展开到父级JSON中,但它只作用于类的属性,而非构造函数参数。你的base是构造参数,且类通过委托实现接口而非直接持有字段,因此@JsonUnwrapped无法让Jackson自动将平级字段映射到base参数。

其他可选方案

如果不想自定义构造函数,也可以编写自定义JsonDeserializer,手动解析JSON节点并构建ExtendedResponseDto实例,但自定义构造函数的方式更简洁,且符合Kotlin数据类的设计习惯。

内容的提问来源于stack exchange,提问作者Hugo Caupert

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 17:47:42