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
еще один способ решить эту проблему. Используйте 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 {...}