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