按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(
{}):Jackson尝试把整个空JSON对象转成Inner,但Inner的委托模式只接受字符串,无法转换,因此抛出构造实例失败的异常。 - 测试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:空JSON
{}中没有inner字段,因此Wrapper的inner属性为null,符合你的断言。 - 测试2:JSON
{"inner":{}}中inner字段是空对象,Inner的prop字段不存在,因此Inner实例的prop为null,但对象能正常创建。 - 测试3:JSON
{"inner":{"prop":"42"}}中prop字段值会被正确映射到Inner的构造器参数,最终prop值为"42"。
关键知识点总结
- 委托模式的适用场景:当你的类可以从单一类型(比如字符串、数字)直接转换而来时使用(比如枚举类用字符串转枚举实例),此时JSON payload应该是对应类型的值,而非对象。
- 属性匹配模式:当需要从JSON对象中提取字段映射到构造器参数时,必须给构造器参数加上
@JsonProperty注解,哪怕参数名和JSON字段名完全一致——这是Jackson识别属性匹配模式的关键。 - Jackson 2.9.x中
Mode.DEFAULT的逻辑确实是:对接受结构化类型(比如自定义对象)的单参数创建者优先使用委托模式,这和你遇到的行为完全一致。
内容的提问来源于stack exchange,提问作者maxxyme
相关产品推荐
相关产品推荐

