Lombok 1.18.0과 Jackson 2.9.6이 함께 작동하지 않음
업데이트 후 역직렬화가 실패합니다.
다음에서 마이크로 서비스를 업데이트했습니다.Spring 1.5.10.RELEASE
로.Spring 2.0.3.RELEASE
또,lombok
부터1.16.14
로.1.18.0
그리고.jackson-datatype-jsr310
부터2.9.4
로.2.9.6
.
JSON 문자열 -
{"heading":"Validation failed","detail":"field must not be null"}
클래스 -
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class ErrorDetail {
private final String heading;
private final String detail;
private String type;
}
메서드 호출 -
ErrorDetail errorDetail = asObject(jsonString, ErrorDetail.class);
역직렬화에 사용되는 방법 -
import com.fasterxml.jackson.databind.ObjectMapper;
// more imports and class defination.
private static <T> T asObject(final String str, Class<T> clazz) {
try {
return new ObjectMapper().readValue(str, clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
오류 -
java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.foo.bar.ErrorDetail` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (String)"{"heading":"Validation failed","detail":"field must not be null"}"; line: 1, column: 2]
Lombok이 생성을 중지했습니다.@ConstructorProperties
버전 1.16.20(changelog 참조)의 컨스트럭터에서는 모듈을 사용하는 Java 9+ 어플리케이션이 파손될 수 있습니다.이 주석에는 생성자의 매개 변수 이름이 포함됩니다(클래스를 컴파일할 때 제거되므로 실행 시 매개 변수 이름을 계속 검색할 수 있도록 해결 방법).기본적으로 주석은 생성되지 않으므로 Jackson은 필드 이름을 생성자 매개 변수에 매핑할 수 없습니다.
해결책 1: 사용@NoArgsConstructor
그리고.@Setter
하지만 당신은 불변성을 잃게 될 것이다(그것이 당신에게 중요하다면).
업데이트: Just(그냥)@NoArgsConstructor
그리고.@Getter
(없음)@Setter
(이유)도 동작할 수 있습니다.이렇게 하면 적어도 일반(비반사) 코드로부터 클래스를 불변 상태로 유지할 수 있습니다.
해결책 2: 행이 포함된 파일을 사용하여 주석을 다시 생성하도록 롬복 구성lombok.anyConstructor.addConstructorProperties = true
. (모듈을 사용하는 경우,java.desktop
모듈 경로 상에 있습니다.)를 추가한 후 정리하고 다시 컴파일합니다.lombok.config
파일.
해결책 3: Jackson의 Builder 지원을 lombok의 Builder 지원(@Jacksonized
)@Builder
/@SuperBuilder
@Randakar에서 설명한 바와 같이 이 질문에 대한 답변입니다.
솔루션 4: 컴파일 시javac
(Java 8 이상), 추가-parameters
명령어로 이동합니다.이렇게 하면 생성된 클래스 파일에 생성자 및 메서드의 매개 변수 이름이 저장되므로 리플렉션을 통해 검색할 수 있습니다.
편집: 이 답변은 좀 오래되었습니다.새로운 것이 있다@Jacksonized
이 답변의 보일러 플레이트의 대부분을 관리하는 https://projectlombok.org/features/experimental/Jacksonized,에서 주석을 작성합니다.
잭슨과 롬복의 플레이를 잘 할 수 있는 가장 좋은 방법은 항상 DTO를 불변하게 만들고, 잭슨에게 빌더를 사용하여 오브젝트로 역직렬화하라고 말하는 것입니다.
불변 객체는 컴파일러가 현장에서 필드를 수정할 수 없는 경우 훨씬 더 적극적인 최적화를 수행할 수 있다는 단순한 이유로 좋은 아이디어입니다.
이를 위해서는 JsonDeserialize와 JsonPojoBuilder의 두 가지 주석이 필요합니다.
예:
@Builder
@Value // instead of @Data
@RequiredArgsConstructor
@NonNull // Best practice, see below.
@JsonDeserialize(builder = ErrorDetail.ErrorDetailBuilder.class)
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class ErrorDetail {
private final String heading;
// Set defaults if fields can be missing, like this:
@Builder.Default
private final String detail = "default detail";
// Example of how to do optional fields, you will need to configure
// your object mapper to support that and include the JDK 8 module in your dependencies..
@Builder.Default
private Optional<String> type = Optional.empty()
@JsonPOJOBuilder(withPrefix = "")
public static final class ErrorDetailBuilder {
}
}
최종 필드가 있는 클래스를 역직렬화하려면 역직렬화할 최종 필드가 포함된 생성자를 선언해야 합니다.
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class ErrorDetail {
private final String heading;
private final String detail;
private String type;
@JsonCreator
public ErrorDetail(@JsonProperty("heading") String heading, @JsonProperty("detail") String detail) {
this.heading = heading;
this.detail = detail;
}
}
또한 Mapper Feature를 사용하여 역직렬화할 때는 Mapper Feature를 사용해야 합니다.ALLOW_FINAL_FILDS_AS_MUTATORTS는 이 속성을 false로 설정합니다.
private static <T> T asObject(final String str, Class<T> clazz) {
try {
return new ObjectMapper().configure(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS,false).readValue(str, clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
솔루션 4
- NoArgsConstructor no no no 。 롬복으로
1.18.8
잭슨입니다.2.9.9
@Builder
@Getter
@AllArgsConstructor
public class EventDTO {
private String id;
private Integer isCancelled;
private String recurringEventId;
private String summary;
private String description;
private String location;
private String startDateTime;
private String endDateTime;
/**
* Make Jackson happy
*/
public EventDTO() {
}
}
「」를 사용합니다.@Data
내 생각에 주석은 좋지 않은 접근법이다.★★★★★★★★★★★★★를 변경해 주세요.@Data
로로 합니다.@Getting
,@Setter
,@EqualsAndHashcode
등....
도움이 된다면 여기에 적어주세요.
갱신하다
을 제안합니다.@Data
@RequiredArgsConstructor
, 가 없는 컨스트럭터입니다.private String type
;
언급URL : https://stackoverflow.com/questions/51464720/lombok-1-18-0-and-jackson-2-9-6-not-working-together
'source' 카테고리의 다른 글
jQuery가 있는 레일에서 눈에 띄지 않는 동적 양식 필드 (0) | 2023.03.20 |
---|---|
react js에서 이미지 src를 동적으로 제공하는 방법 (0) | 2023.03.20 |
Form 7 문의 - 이메일 발송 시 커스텀 기능 추가 (0) | 2023.03.20 |
엄격한 기준:'의 선언은 '와 호환되어야 합니다. (0) | 2023.03.20 |
JSON.stringify가 RangeError를 슬로우합니다.거대한 개체의 문자열 길이가 잘못되었습니다. (0) | 2023.03.20 |