问题
Jackson can deserialize json for the following class in 2.6.5 but fails in 2.8.8.
Model:
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
}
]
}
The exception is:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "childId" (class Parent), not marked as ignorable (2 known properties: "children", "id"])
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?
回答1:
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".
A delegate creator allows Jackson to deserialize json for one type of object into another type of Java object.
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.
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));
Update
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.
来源:https://stackoverflow.com/questions/47598037/jackson-deserialization-fails-because-of-non-default-constructor-created-by-lomb