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

Jackson反序列化报错:构造函数参数无属性名问题排查与解决

Jackson反序列化报错:InvalidDefinitionException 问题排查与解决

问题场景

使用Jackson反序列化JSON时抛出如下错误:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid type definition for type `stack.overflow.model.dto.response.QuestionCommentResponseDto`: Argument #0 of constructor [constructor for `stack.overflow.model.dto.response.QuestionCommentResponseDto` (6 args), annotations: {interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)} has no property name (and is not Injectable): can not use as property-based Creator
 at [Source: (String)"{"data":{"id":1,"questionId":1,"createdDate":"2023-06-03T20:16:57.238883","modifiedDate":"2023-06-03T20:16:57.238883","text":"text","owner":{"id":1,"username":"mickey_m"}}}";; line: 1, column: 1]

涉及的DTO代码如下:

QuestionCommentResponseDto

@Getter
public class QuestionCommentResponseDto {
    private final Long id;
    private final Long questionId;
    private final LocalDateTime createdDate;
    private final LocalDateTime modifiedDate;
    private final String text;
    @Setter
    private AccountResponseDto owner;

    public QuestionCommentResponseDto(Long id, Long questionId, LocalDateTime createdDate,
                                      LocalDateTime modifiedDate, String text) {
        this.id = id;
        this.questionId = questionId;
        this.createdDate = createdDate;
        this.modifiedDate = modifiedDate;
        this.text = text;
    }
    @JsonCreator
    private QuestionCommentResponseDto(Long id, Long questionId, LocalDateTime createdDate,
                                      LocalDateTime modifiedDate, String text,
                                      AccountResponseDto owner) {
        this(id, questionId, createdDate, modifiedDate, text);
        this.owner = owner;
    }
// equals() and hashcode()
}

AccountResponseDto

// 关联DTO
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class AccountResponseDto {

    private Long id;
    private String username;
// equals() and hashcode()
}

错误含义与疑问解答

  1. 错误含义:Jackson无法使用你标注了@JsonCreator的6参数私有构造函数完成反序列化,原因是该构造函数的参数未绑定对应JSON属性名,Jackson无法将JSON中的键值对映射到构造函数参数上。
  2. Argument #0是否指id:是的,参数索引从0开始计数,Argument #0就是构造函数的第一个参数id。

问题原因

Jackson使用@JsonCreator注解的构造函数时,默认需要明确每个参数对应的JSON属性名。你仅给构造函数添加了@JsonCreator,但未给每个参数标注@JsonProperty指定对应JSON键名,导致Jackson无法自动匹配参数与JSON字段。

解决方案

方式一:给构造函数参数添加@JsonProperty注解

给@JsonCreator标注的构造函数的每个参数加上@JsonProperty,明确对应JSON属性名:

@JsonCreator
private QuestionCommentResponseDto(
    @JsonProperty("id") Long id,
    @JsonProperty("questionId") Long questionId,
    @JsonProperty("createdDate") LocalDateTime createdDate,
    @JsonProperty("modifiedDate") LocalDateTime modifiedDate,
    @JsonProperty("text") String text,
    @JsonProperty("owner") AccountResponseDto owner
) {
    this(id, questionId, createdDate, modifiedDate, text);
    this.owner = owner;
}

方式二:使用Jackson参数名称模块(推荐)

若项目基于Java 8+,可引入Jackson参数名称模块,让Jackson通过反射直接获取参数名,无需手动添加@JsonProperty:

  1. 引入Maven依赖:
<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-parameter-names</artifactId>
    <version>你的Jackson版本</version>
</dependency>
  1. 注册模块到ObjectMapper(Spring项目可通过配置类自动注册):
@Configuration
public class JacksonConfig {
    @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper()
                .registerModule(new ParameterNamesModule());
    }
}

额外优化方案

由于owner字段已有@Setter,可直接移除6参数私有构造函数,仅给5参数构造函数添加@JsonCreator(配合@JsonProperty或参数名称模块),Jackson会在实例化后自动通过setter注入owner字段:

@Getter
public class QuestionCommentResponseDto {
    private final Long id;
    private final Long questionId;
    private final LocalDateTime createdDate;
    private final LocalDateTime modifiedDate;
    private final String text;
    @Setter
    private AccountResponseDto owner;

    @JsonCreator
    public QuestionCommentResponseDto(
        @JsonProperty("id") Long id,
        @JsonProperty("questionId") Long questionId,
        @JsonProperty("createdDate") LocalDateTime createdDate,
        @JsonProperty("modifiedDate") LocalDateTime modifiedDate,
        @JsonProperty("text") String text
    ) {
        this.id = id;
        this.questionId = questionId;
        this.createdDate = createdDate;
        this.modifiedDate = modifiedDate;
        this.text = text;
    }
// equals() and hashcode()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 06:35:01