jackson InvalidDefinitionException 异常原因及解决方案

一、问题背景

这是一次在给已有类添加新字段时,因为原来的字段已有构造方法,为了避免对老代码修改产生bug,所以新字段我把老构造方法重新复制改了一下,然后就报如下错误

java.lang.IllegalArgumentException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException
示例日志如下

Exception in thread "main" java.lang.IllegalArgumentException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Conflicting property-based creators: already had explicitly marked creator [constructor for xxx.User, annotations: {interface java.beans.ConstructorProperties=@java.beans.ConstructorProperties(value=[id, name, age])}], encountered another: [constructor for xxx.User, annotations: {interface java.beans.ConstructorProperties=@java.beans.ConstructorProperties(value=[id, name])}]
 at [Source: (String)"{"name":"张三","id":"1234","age":11}"; line: 1, column: 1]

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Conflicting property-based creators: already had explicitly marked creator [constructor for xxx.User, annotations: {interface java.beans.ConstructorProperties=@java.beans.ConstructorProperties(value=[id, name, age])}], encountered another: [constructor for xxx.User, annotations: {interface java.beans.ConstructorProperties=@java.beans.ConstructorProperties(value=[id, name])}]
 at [Source: (String)"{"name":"张三","id":"1234","age":11}"; line: 1, column: 1]
	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:62)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:227)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:143)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:414)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:349)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
	at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
	at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:491)
	at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4669)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4478)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3434)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3402)

二、问题原因

1.问题代码

class User {
    private String id;
    private String name;
    private Integer age;


    @ConstructorProperties({"id", "name"})
    public User(String id, String name) {
        this.id = id;
        this.name = name;
    }

    @ConstructorProperties({"id", "name", "age"})
    public User(String id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return new StringJoiner(", ", User.class.getSimpleName() + "[", "]").add("id='" + id + "'").add("name='" + name + "'").add("age=" + age).toString();
    }
  • 因为是复制出来改的,导致有2个构造方法,并且两个方法上都有 @ConstructorProperties 注解,然后 jackson 在创建对象时不知道使用哪个构造方法了,所以报错

三、解决方案

  • 把多余的构造方法去掉,使用字段多的构造方法
  • 一个类只能有一个构造方法使用 @ConstructorProperties