Ошибка десериализации Джексона из-за нестандартного конструктора, созданного lombok

Джексон может десериализовать json для следующего класса в 2.6.5, но терпит неудачу в 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"])

Я обнаружил, что конструктор Child, созданный lombok, вызывает эту ошибку. Когда я избавляюсь от аннотации ломбок или создаю конструктор вручную, это перестает происходить. В любом случае он должен использовать конструктор Child () без аргументов. Что вызывает эту проблему?


person Kylos    schedule 01.12.2017    source источник


Ответы (1)


Lombok добавляет аннотацию @ConstructorProperties({"parent"}) к сгенерированному конструктору. В Jackson 2.8.8 это приводит к тому, что конструктор обрабатывается как «создатель делегата».

Создатель делегата позволяет Джексону десериализовать json для одного типа объекта в другой тип объекта Java.

В этом случае, поскольку lombok генерирует конструктор @ConstructorProperties({"parent"}) Child(Parent parent) {...}, Джексон попытается десериализовать дочерний json как родительский объект, который затем может быть передан в конструктор для создания дочернего объекта. Затем он вызывает исключение, потому что childId не является полем в Parent.

Один из обходных путей - настроить ObjectMapper, используемый для десериализации JSON, с помощью пользовательского JacksonAnnotationIntrospector, чтобы он не интерпретировал конструктор как создателя делегата.

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector().setConstructorPropertiesImpliesCreator(false));

Обновить

Версия 1.16.20 проекта lombok действительно по умолчанию lombok.anyConstructor.suppressConstructorProperties имеет значение true, как указал Роэл в своем комментарии. Это делает обновление lombok до последней версии еще одним решением этой проблемы.

person Kylos    schedule 01.12.2017
comment
Я полагаю, вы правы. Раньше был параметр аннотации suppressConstructorProperties, но его давно нет. - person maaartinus; 02.12.2017
comment
Вы все еще можете отключить его в файле lombok.config, используя lombok.anyConstructor.suppressConstructorProperties = true. Мы рассматриваем возможность сделать это значение по умолчанию, поскольку в jdk9 для этого требуется зависимость от другого модуля. - person Roel Spilker; 04.12.2017