杰克逊反序列化失败,因为lombok创建了非默认构造函数 [英] Jackson Deserialization Fails because of non-default constructor created by lombok
问题描述
Jackson可以在2.6.5中反序列化以下类的json,但在2.8.8中失败.
Jackson can deserialize json for the following class in 2.6.5 but fails in 2.8.8.
型号:
public static class Parent {
public long id;
public List<Child> children;
}
@RequiredArgsConstructor
public static class Child {
public long childId;
@NonNull
@JsonIgnore
public Parent parent;
public Child() { }
}
JSON:
{
"id": 1,
"children": [
{
"childId": 2
}
]
}
例外是:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "childId" (class Parent), not marked as ignorable (2 known properties: "children", "id"])
我发现由lombok创建的Child构造函数导致了此错误.当我摆脱了lombok批注时,或者如果我手动创建了构造函数,这种情况就会停止.无论哪种方式,都应该使用no-args Child()构造函数.是什么导致此问题?
I have found that the Child constructor created by lombok is causing this error. When I get rid of the lombok annotation or if I create the constructor manually, this stops happening. Either way, it should be using the no-args Child() constructor. What is causing this issue?
推荐答案
Lombok将注释@ConstructorProperties({"parent"})
添加到生成的构造函数中.在Jackson 2.8.8中,这导致构造函数被视为委托创建者".
Lombok adds the annotation @ConstructorProperties({"parent"})
to the generated constructor. In Jackson 2.8.8, this causes the constructor to be treated as a "delegate creator".
委托创建者允许Jackson将一种类型的对象的json反序列化为另一种Java对象.
A delegate creator allows Jackson to deserialize json for one type of object into another type of Java object.
在这种情况下,因为lombok生成了构造函数@ConstructorProperties({"parent"}) Child(Parent parent) {...}
,Jackson会尝试将子json反序列化为Parent对象,然后可以将其传递给构造函数以创建Child.然后会抛出异常,因为childId不是Parent中的字段.
In this case, because lombok generates the constructor @ConstructorProperties({"parent"}) Child(Parent parent) {...}
Jackson will try to deserialize the child json as a Parent object, which could then be passed into the constructor to create a Child. It then throws the exception because childId is not a field in Parent.
一种解决方法是使用自定义JacksonAnnotationIntrospector
配置用于反序列化JSON的ObjectMapper
,这样它就不会将构造方法解释为委托创建者.
One workaround is to configure the ObjectMapper
used to deserialize the JSON with a custom JacksonAnnotationIntrospector
so it won't interpret the constructor as a delegate creator.
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector().setConstructorPropertiesImpliesCreator(false));
更新
项目lombok的版本1.16.20确实确实默认将lombok.anyConstructor.suppressConstructorProperties设置为true,正如Roel指出的那样. 因此,将lombok升级到最新版本是解决此问题的另一种方法.
Version 1.16.20 of project lombok did indeed default lombok.anyConstructor.suppressConstructorProperties to true as Roel indicated might happen in his comment. That makes upgrading lombok to the latest version another fix for this issue.
这篇关于杰克逊反序列化失败,因为lombok创建了非默认构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!