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

按Javadoc使用Jackson @JsonCreator反序列化失败及模式疑问

问题分析与解决方案

我来帮你拆解一下你遇到的@JsonCreator使用问题,核心是对委托模式和属性匹配模式的触发条件理解有偏差,结合Jackson 2.9.9的特性,咱们一步步理清楚:

为什么你的测试会报错?

先看你写的实体类逻辑:

  • Wrapper的@JsonCreator是单参数构造器,没有给参数加@JsonProperty,触发了Jackson的委托模式:Jackson会尝试把整个JSON payload直接转换成构造器参数的类型(Inner),而不是提取JSON里的inner字段值传给构造器。
  • Inner的@JsonCreator也是单String参数的委托模式,意味着Jackson只能把纯字符串类型的JSON值转换成Inner实例,没法处理对象类型(比如{}或{"prop":"42"})。

对应到你的三个测试:

  1. 测试1({}):Jackson尝试把整个空JSON对象转成Inner,但Inner的委托模式只接受字符串,无法转换,因此抛出构造实例失败的异常。
  2. 测试2/3({"inner":{}}/{"inner":{"prop":"42"}}):委托模式下Jackson把整个{"inner":{}}当成Inner的输入,而Inner类没有inner属性,因此抛出未识别字段的异常。

修正后的代码

你需要调整@JsonCreator的使用方式,明确告诉Jackson要基于JSON字段匹配构造器参数,而不是用委托模式:

Wrapper类(给构造器参数加@JsonProperty)

public class Wrapper {
    private Inner inner;
    
    @JsonCreator
    public Wrapper(@JsonProperty("inner") Inner inner) {
        this.inner = inner;
    }
    
    public Inner getInner() {
        return inner;
    }
}

Inner类(同样给构造器参数加@JsonProperty)

public class Inner {
    private String prop;
    
    @JsonCreator
    public Inner(@JsonProperty("prop") String prop) {
        this.prop = prop;
    }
    
    public String getProp() {
        return prop;
    }
}

修正后测试的执行逻辑

  1. 测试1:空JSON{}中没有inner字段,因此Wrapper的inner属性为null,符合你的断言。
  2. 测试2:JSON{"inner":{}}中inner字段是空对象,Inner的prop字段不存在,因此Inner实例的prop为null,但对象能正常创建。
  3. 测试3:JSON{"inner":{"prop":"42"}}中prop字段值会被正确映射到Inner的构造器参数,最终prop值为"42"。

关键知识点总结

  • 委托模式的适用场景:当你的类可以从单一类型(比如字符串、数字)直接转换而来时使用(比如枚举类用字符串转枚举实例),此时JSON payload应该是对应类型的值,而非对象。
  • 属性匹配模式:当需要从JSON对象中提取字段映射到构造器参数时,必须给构造器参数加上@JsonProperty注解,哪怕参数名和JSON字段名完全一致——这是Jackson识别属性匹配模式的关键。
  • Jackson 2.9.x中Mode.DEFAULT的逻辑确实是:对接受结构化类型(比如自定义对象)的单参数创建者优先使用委托模式,这和你遇到的行为完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 15:44:08