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

为何Jackson反序列化单字段DTO需无参构造,多字段则无需?

为什么单字段DTO需要@NoArgsConstructor才能被Jackson反序列化,多字段却不需要?

核心原因:Jackson对单参数构造器的特殊处理逻辑

Jackson在反序列化JSON对象时,构造器的选择逻辑会因类的字段数量不同产生差异:

1. 多字段DTO的情况(如你的StudentCreationDTO)

当类有多个字段,且存在一个参数数量与JSON字段数量完全匹配的构造器(这里是@AllArgsConstructor生成的构造器),Jackson会:

  • 通过反射获取构造器的参数名称(Spring Boot默认开启参数名称保留,Lombok的@AllArgsConstructor会配合编译器保留参数名)
  • 将JSON中的键与构造器参数名一一匹配,直接调用该构造器实例化对象,无需依赖无参构造器或setter方法。

你的StudentCreationDTO有4个字段,@AllArgsConstructor生成的构造器正好对应4个参数,Jackson能精准匹配每个参数对应的JSON字段,因此反序列化正常。

2. 单字段DTO的情况(如你的SubjectCreationDTO)

当类只有一个字段时,Jackson会优先尝试将JSON的原始值(比如纯字符串"Math")直接传入单参数构造器。但你发送的是JSON对象({"title":"Math"}),此时Jackson会陷入矛盾:

  • 无法将整个JSON对象直接传给接收String类型的单参数构造器;
  • 又找不到无参构造器来先实例化对象,再通过setter方法赋值。

最终就会抛出你遇到的错误:cannot deserialize from Object value (no delegate- or property-based Creator)。

两种可选解决方案

方案1:添加@NoArgsConstructor

给单字段DTO加上@NoArgsConstructor,让Jackson先创建空对象,再通过@Setter生成的方法设置字段值:

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class SubjectCreationDTO {
    private String title;
}

方案2:给单参数构造器的参数添加@JsonProperty

显式告诉Jackson单参数构造器的参数对应JSON中的哪个字段,让Jackson能正确映射JSON对象的字段到构造器参数:

@AllArgsConstructor
@Getter
@Setter
public class SubjectCreationDTO {
    @JsonProperty("title")
    private String title;
}

(注:Lombok 1.18.16及以上版本,字段上的@JsonProperty会自动应用到@AllArgsConstructor生成的构造器参数上,无需手动编写构造器)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 03:16:25