ObjectMapper не может десериализоваться без конструктора по умолчанию после обновления до Spring Boot 2

у меня есть следующие DTOs:

@Value
public class PracticeResults {
    @NotNull
    Map<Long, Boolean> wordAnswers;
}

@Value
public class ProfileMetaDto {

    @NotEmpty
    String name;
    @Email
    String email;
    @Size(min = 5)
    String password;
}

@Value-это аннотация Ломбока, которая генерирует конструктор. Это означает, что этот класс не имеет конструктора без аргументов.

я использовал Spring Boot 1.4.3.RELEASE и objectmapper bean смогли десериализовать такой объект из json.

после обновления до Spring Boot 2.0.0.M7 я получаю следующее исключение:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of PracticeResults (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

версия Джексона, используемая в Spring Boot 1.4.3, -2.8.10 и для весенней загрузки 2.0.0.М7 -2.9.2.

Я попытался Google эту проблему, но нашел только решения с @JsonCreator или @JsonProperty.

Итак, почему он работает с Spring Boot 1.4.3 и не работает с Spring Boot 2? Можно ли настроить bean так же, как и более старая версия?

3 ответов


из-за изменения Ломбок версии 1.16.20 вам необходимо установить следующее свойство в вашем lombok.config file (если у вас нет этого файла, вы можете создать его в корне проекта):

lombok.anyConstructor.addConstructorProperties=true

это описано в Ломбок изменений: https://projectlombok.org/changelog.

после этого значение @должно быть снова принято Джексоном.

вас может заинтересовать следующая связанная проблема GitHub здесь: https://github.com/rzwitserloot/lombok/issues/1563


я обновил версию lombok до: "org.projectlombok: lombok: 1.18.0' и это сработало для меня.


еще один способ решить эту проблему. Используйте Jackson модуль имен параметров, который включен в spring boot 2 по умолчанию. После этого Джексон может десериализовать объекты. Но он работает, только если у вас есть более 1 свойства в объекте. В случае одного свойства, я получаю следующее сообщение об ошибке:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `SomeClassName` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

из-за следующего:

маркер аннотация, которая может быть использована для определения конструкторов и заводских методов как один для использования создание новых экземпляров связанного класса.

Примечание: при аннотации методов создателя (конструкторы, заводские методы) метод должен быть:

  • конструктор с одним аргументом / заводской метод без JsonProperty аннотация для аргумента: если это так, это так называемый "delegate creator", в этом случае Джексон сначала связывает JSON в тип аргумента, а затем вызывает creator. Это часто используется в сочетании с JsonValue (используется для сериализация.)
  • конструктор / заводской метод, где каждый аргумент аннотируется либо JsonProperty или JacksonInject, чтобы указать имя свойства для привязки к

Также обратите внимание, что все JsonProperty аннотации должны указывать фактическое имя (не пустая строка для "default"), если вы не используете один из модулей расширения, которые могут определять имя параметра; это потому, что версии JDK по умолчанию до 8 не смогли сохранить и / или получить имена параметров из байткод. Но с JDK 8 (или с помощью вспомогательных библиотек, таких как Paranamer, или других языков JVM, таких как Scala или Kotlin), указание имени необязательно.

для обработки этого случая с Ломбоком я использовал следующее обходное решение:

@Value
@AllArgsConstructor(onConstructor = @__(@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)))
class SomeClassName {...}