Spring Boot 2로 업그레이드한 후 Object Mapper가 기본 컨스트럭터 없이 역직렬화할 수 없음
DTO는 다음과 같습니다.
@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는 생성자를 생성하는 롬복 주석입니다.즉, 이 클래스에는 no-arg 생성자가 없습니다.
Spring Boot 1.4.3을 사용했습니다.릴리즈 및ObjectMapperbean은 이러한 오브젝트를 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에서 사용되는 Jackson 버전은2.8.10및 Spring Boot 2.0.0 용입니다.M7은2.9.2.
이 문제를 구글로 검색하려고 했지만 해결 방법만 찾았습니다.@JsonCreator또는@JsonProperty.
그러면 Spring Boot 1.4.3에서는 동작하고 Spring Boot 2에서는 동작하지 않는 이유는 무엇일까요?이전 버전과 동일하게 동작하도록 bean을 설정할 수 있습니까?
Lombok 버전 1.16.20의 변경을 어기고 있기 때문에 다음 속성을 설정할 필요가 있습니다.lombok.config파일(이 파일이 없는 경우 프로젝트 루트에 파일을 만들 수 있습니다):
lombok.anyConstructor.addConstructorProperties=true
이는 Lombok changelog(https://projectlombok.org/changelog)에 설명되어 있습니다.
그 후 잭슨은 @Value를 다시 인정해야 합니다.
GitHub 관련 이슈에 관심이 있으실 수도 있습니다.단, GitHub 관련 이슈에 대한 것입니다.@Data: https://github.com/rzwitserloot/lombok/issues/1563
이 문제를 해결할 수 있는 한 가지 방법이 있습니다.잭슨 파라미터 이름 모듈을 사용합니다.이것은 기본적으로 스프링부트 2에 포함되어 있습니다.이 후에 잭슨은 오브젝트를 역직렬화 할 수 있다.그러나 이 기능은 개체에 둘 이상의 속성이 있는 경우에만 작동합니다.단일 속성인 경우 다음 오류 메시지가 표시됩니다.
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인수에 대한 주석: 그렇다면 이것은 소위 "위임 크리에이터"입니다.이 경우 잭슨은 먼저 JSON을 인수의 유형에 바인드한 다음 크리에이터를 호출합니다.이것은 종종 와 함께 사용됩니다.JsonValue(시리얼라이제이션에 사용).- 모든 인수에 다음 중 하나를 주석으로 붙이는 생성자/공장 메서드
JsonProperty★★★★★★★★★★★★★★★★★」JacksonInject, 모든 「 」, 「 」가 것에 .
JsonProperty주석은 파라미터 이름을 검출할 수 있는 확장 모듈 중 하나를 사용하지 않는 한 실제 이름을 지정해야 합니다.이는 8 이전 버전의 JDK에서는 바이트 코드에서 파라미터 이름을 저장하거나 가져올 수 없기 때문입니다.그러나 JDK 8(또는 Paranamer와 같은 도우미 라이브러리 또는 Scala나 Kotlin과 같은 다른 JVM 언어를 사용)에서는 이름을 지정하는 것은 옵션입니다.
Lombok을 사용하여 이 문제를 처리하기 위해 다음 해결 방법을 사용했습니다.
@Value
@AllArgsConstructor(onConstructor = @__(@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)))
class SomeClassName {...}
클래스 내에 최종 필드가 몇 개 있고 특정 컨스트럭터를 사용하여 POJO를 역직렬화하는 Object creator를 원하는 경우@Data합니다.@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)필요한 생성자 매개변수를 구체화한다.@JsonProperty("<field_name>")예를 다음에 나타냅니다.
package test.model;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.Date;
@Data
public class KafkaEventPojo {
private final String executionId;
private final String folder;
private final Date created_at;
private Date updated_at;
// ... other params
/**
* Instantiates a new Kafka event pojo.
*
* @param executionId the execution or flow id of the event lifecycle
* @param folder the folder to be retrieved
*/
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public KafkaEventPojo(@JsonProperty("executionId") String executionId, @JsonProperty("folder") String folder) {
this(executionId, folder, new Date(System.currentTimeMillis()));
}
private KafkaEventPojo(String executionId, String folder, Date date) {
this.executionId = executionId;
this.folder = folder;
this.created_at = date;
this.updated_at = date;
}
// ... other logic
}
이 문제와 필드 없는 디폴트 컨스트럭터를 만들면 문제가 사라지게 되는 해결책이 있었습니다.
했지만, 은 이 하는 것을 하지 않았다: this에 、 만에 、 루 i 、 루 i 、 i i i i i i 。(mode = JsonCreator.Mode.PROPERTIES)
제 고민을 정말 해결한 건@JsonProperty이치노
최종 결과는 다음과 같습니다.
@Value
public class ServerTimeResponse {
long serverTime;
@JsonCreator
public ServerTimeResponse(@JsonProperty("serverTime") long serverTime) {
this.serverTime = serverTime;
}
}
다른 '더 넣어야 ', '더 많이 넣어야 한다', '더 많이 넣어야 한다', '더 많이 넣어야 한다' 이런 에요.@Value에게 롬복의 을 @JsonCreator 상에서
@AllArgsConstructor(onConstructor_={@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)})
JDK8+ 를 사용하고 있는 경우는, 여기의 다른 회답과는 약간 다른 구문을 참조해 주세요(이 구문은 javadoc 에 기재되어 있습니다).
freefair gradle에 을 추가하도록 .build.gradle:
lombok {
config['lombok.anyConstructor.addConstructorProperties'] = 'true'
}
중 이한 경우 에서 "Native Mode"를 입니다.@RegisterForReflection합니다.
링크에 대한 정보 검색
롬복 버전을 org.projectlombok:lombok:1.18.0'으로 업그레이드하여 사용할 수 있게 되었습니다.
언급URL : https://stackoverflow.com/questions/48330613/objectmapper-cant-deserialize-without-default-constructor-after-upgrade-to-spri
'programing' 카테고리의 다른 글
| C# var 키워드에 상당하는 VB.NET (0) | 2023.04.07 |
|---|---|
| 리액트 라우터가 aws s3 버킷에서 작동하지 않음 (0) | 2023.04.02 |
| 리액트 테스트 라이브러리를 사용하여 장치 테스트에서 작동하도록 RizeObserver를 시뮬레이션하는 방법 (0) | 2023.04.02 |
| .htaccess & WordPress: RewriteRule에서 폴더 제외 (0) | 2023.04.02 |
| fetch() 예기치 않은 입력 끝 (0) | 2023.04.02 |