잭슨과 롬복에게 함께 일하게 할 수 없다.
나는 잭슨과 롬복의 결합을 실험하고 있다.제 수업은 다음과 같습니다.
package testelombok;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Value;
import lombok.experimental.Wither;
@Value
@Wither
@AllArgsConstructor(onConstructor=@__(@JsonCreator))
public class TestFoo {
@JsonProperty("xoom")
private String x;
private int z;
}
package testelombok;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xebia.jacksonlombok.JacksonLombokAnnotationIntrospector;
import java.io.IOException;
public class TestLombok {
public static void main(String[] args) throws IOException {
TestFoo tf = new TestFoo("a", 5);
System.out.println(tf.withX("b"));
ObjectMapper om = new ObjectMapper().setAnnotationIntrospector(new JacksonLombokAnnotationIntrospector());
System.out.println(om.writeValueAsString(tf));
TestFoo tf2 = om.readValue(om.writeValueAsString(tf), TestFoo.class);
System.out.println(tf2);
}
}
classpth에 추가할 JAR은 다음과 같습니다.
Lombok: https://projectlombok.org/downloads/lombok.jar (버전 1.16.10)
잭슨 주석: http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.8.2/jackson-annotations-2.8.2.jar
잭슨 코어: http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.8.2/jackson-core-2.8.2.jar
잭슨 데이터바인드: http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.8.2/jackson-databind-2.8.2.jar
Netbeans를 사용하여 컴파일하고 있습니다(관련성이 없다고 생각합니다만, 어쨌든 완벽하고 충실하게 재현할 수 있도록 보고합니다).은 "5개의 JAR"라는되어 있습니다.lib
폴더 내 ('프로젝트 폴더'와 src
", "nbproject
", "test
및 " " " "build
프로젝트 속성의 "Add JAR/Folder" 버튼을 사용하여 Netbeans에 추가했더니 위와 같은 순서로 나열되어 있습니다.이 프로젝트는 표준 "Java 애플리케이션" 유형의 프로젝트입니다.
또한 Netbeans 프로젝트는 "저장 시 컴파일 안 함", "디버깅 정보 생성", "리포트 폐지된 API", "자바 의존관계 추적", "액티브 주석 처리 중" 및 "액티브 주석 처리 중"으로 구성된다.Netbeans에서 주석 프로세서 또는 주석 처리 옵션이 명시적으로 구성되지 않았습니다.또, 그 "-Xlint:all
명령줄 옵션은 컴파일러 명령줄에 전달되며 컴파일러는 외부 VM에서 실행됩니다.
javac 버전은 1.8.0_72이고 java 버전은 1.8.0_72-b15입니다.넷콩은 8.1입니다.
내 프로젝트는 잘 정리되어 있다.그러나 실행 시 예외가 발생합니다.이 예외는 쉽게 또는 명백하게 수정 가능한 것으로 보이는 것은 아닌 것 같습니다.스택 트레이스를 포함한 출력을 다음에 나타냅니다.
TestFoo(x=b, z=5)
{"z":5,"xoom":"a"}
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Argument #0 of constructor [constructor for testelombok.TestFoo, annotations: {interface java.beans.ConstructorProperties=@java.beans.ConstructorProperties(value=[x, z]), interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
at [Source: {"z":5,"xoom":"a"}; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:296)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:269)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:475)
at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3890)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3785)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2833)
at testelombok.TestLombok.main(TestLombok.java:14)
Caused by: java.lang.IllegalArgumentException: Argument #0 of constructor [constructor for testelombok.TestFoo, annotations: {interface java.beans.ConstructorProperties=@java.beans.ConstructorProperties(value=[x, z]), interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._addDeserializerConstructors(BasicDeserializerFactory.java:511)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:323)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:253)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:219)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:141)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:406)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:352)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
... 7 more
저는 이미 그 칼로 무작위로 찌르려고 했어요.@Value
★★★★★★★★★★★★★★★★★」@AllArgsConstructor
주석을 달았지만 더 이상 나아지게 할 수는 없었어요
예외를 검색해 보니 잭슨에 대한 오래된 버그 보고서와 열려있지만 다른 것과 관련이 있는 것 같습니다.단, 이 버그의 개요나 수정 방법에 대해서는 아직 알 수 없습니다.그리고 다른 곳에서는 쓸만한 것을 찾을 수 없었다.
제가 하려고 하는 것은 lombok과 jackson 둘 다 매우 기본적인 사용법이기 때문에, 이 문제를 어떻게 해결할지에 대한 유용한 정보를 찾을 수 없었던 것이 이상하다고 생각합니다.내가 뭘 놓쳤나?
"롬복 쓰지 마" "잭슨 쓰지 마"라고 말하는 것 말고, 이 문제를 해결할 방법을 알고 있는 사람?
불변하지만 롬복과 잭슨을 사용한 json 시리얼화 POJO를 원한다면.합니다.@JsonPOJOBuilder(withPrefix = "")
이 솔루션을 사용해 봤는데 매우 잘 작동합니다. 사용방법 »
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import lombok.Builder;
import lombok.Value;
@JsonDeserialize(builder = Detail.DetailBuilder.class)
@Value
@Builder
public class Detail {
private String url;
private String userName;
private String password;
private String scope;
@JsonPOJOBuilder(withPrefix = "")
public static class DetailBuilder {
}
}
@Builder
의 빈 않는 를 빈 주석으로 수 .withPrefix
mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
@Override
public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) {
if (ac.hasAnnotation(JsonPOJOBuilder.class)) {//If no annotation present use default as empty prefix
return super.findPOJOBuilderConfig(ac);
}
return new JsonPOJOBuilder.Value("build", "");
}
});
빈 는 빈 빌더 클래스로 할 수 .@JsonPOJOBuilder
석입니니다다
불변+롬복+잭슨은 다음 방법으로 달성할 수 있습니다.
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.Value;
@Value
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
@AllArgsConstructor
public class LocationDto {
double longitude;
double latitude;
}
class ImmutableWithLombok {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
String stringJsonRepresentation = objectMapper.writeValueAsString(new LocationDto(22.11, 33.33));
System.out.println(stringJsonRepresentation);
LocationDto locationDto = objectMapper.readValue(stringJsonRepresentation, LocationDto.class);
System.out.println(locationDto);
}
}
나는 위의 몇 가지를 시도했지만 모두 변덕스러웠다.나에게 정말 효과가 있었던 것은 내가 여기서 찾은 대답이다.
프로젝트의 루트 디렉토리에 lombok.config 파일을 추가합니다(아직 추가하지 않은 경우).
lombok.config
그리고 이것을 안에 붙인다.
lombok.anyConstructor.addConstructorProperties=true
다음으로 다음과 같이 pojo를 정의할 수 있습니다.
@Data
@AllArgsConstructor
public class MyPojo {
@JsonProperty("Description")
private String description;
@JsonProperty("ErrorCode")
private String errorCode;
}
주석을 사용한 예를 다음에 나타냅니다.
import lombok.Value;
import lombok.Builder;
import lombok.extern.jackson.Jacksonized;
@Jacksonized
@Builder
@Value
public class User {
private final String name;
private final String surname;
}
「」를 사용할 .@Builder
석입니니다다
문제를 그것을 '해결'해서 '.이 문제를 해결하려면suppressConstructorProperties = true
파예예예예 ( 예예::: ) :
@Value
@Wither
@AllArgsConstructor(suppressConstructorProperties = true)
public class TestFoo {
@JsonProperty("xoom")
private String x;
private int z;
}
잭슨은 컨스트럭터에 주석을 추가하는 것을 좋아하지 않는 것 같습니다.그suppressConstructorProperties = true
파라미터는 Lombok에게 추가하지 않도록 지시합니다(기본값으로 추가).
할 수 은 두 가 있습니다.@Builder
잭슨이랑 같이.
옵션 1
- 개인 기본 noArgs 및 allArgs 컨스트럭터를 추가합니다.
@Builder
@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Person {
@JsonProperty("user_name")
private String name;
}
옵션 2
이 기사 덕분에.
잭슨은 빌더 방식이 다음과 같이 시작되기를 기대합니다..withProperty(...)
에서는 지지 but but but but but but but but가 생성됩니다..property(...)
.
작성자 클래스를 직접 만들어 잭슨 주석을 추가할 수 있습니다.그런 다음 Lombok은 이 클래스를 재사용하고 모든 빌더 메서드를 추가합니다.
@JsonDeserialize(builder = MyDto.MyDtoBuilder.class)
@Builder
@Getter
public class MyDto {
@JsonProperty("user_id")
private String userId;
@JsonPOJOBuilder(withPrefix = "")
@JsonIgnoreProperties(ignoreUnknown = true)
public static class MyDtoBuilder {
}
}
- 너는 수작업이 필요하다.
- 빌더를 직접 쓰는 것보다 훨씬 낫습니다.
- 이 에도 ''와 같은 이 있다는 점에 해 주세요.
@JsonIgnorePropertie
으로 리팩터의 을 바꾸지 입니다.MyDtoBuilder
Lombok/Jackson은 Lombok/Jackson이다.
업데이트: 옵션 1에 추가된 다른 솔루션(lombok 1.18.20 및 스프링 부트 2.4.5에서 테스트됨)이 발견되었습니다.
추가 주석 없이 더 단순하게 수행할 수 있으며 상속이 문제일 수 있습니다. 즉, 하위 클래스도 역직렬화 가능해야 합니다.예를 들어 다음과 같습니다.
요건:
lombok.config
프로젝트 루트 디렉토리 내에는 다음 내용을 포함하는 본문이 있습니다.
lombok.anyConstructor.addConstructorProperties=true
/** The parent class **/
@Value
@NonFinal
@SuperBuilder
@RequiredArgsConstructor
public class Animal {
String name;
}
/** The child class **/
@Value
@SuperBuilder
@RequiredArgsConstructor
public class Cat {
Long tailLength;
@ConstructorProperties({"tailLength", "name})
public Cat(Long tailLength, String name) {
super(name);
this.tailLength = tailLength;
}
}
그 내용:
- 부모 필드를 포함한 오브젝트 작성 가능
- 「」로 .
ObjectMapper
잭슨은 - 상위 클래스 및 하위 클래스의 인스턴스는 변경할 수 없습니다.
다른 예에 대한 나의 조언:
- 특정 클래스에 사용자 지정 주석을 배치하지 마십시오. 그러면 클래스가 불균일해집니다.어쨌든, 언젠가는 범용 솔루션에 도달하게 될 것입니다.
Jackson
Jackson이 주석 없이 직렬화/비직렬화를 수행할 수 있는 경우 생성자의 모든 필드에 주석을 달면 커플링이 생성됩니다.- 「 」를하지 주세요.
@AllArgsConstructor
불변의 실체를 위해.클래스에 최종 필드만 있는 경우 개념적으로 올바른 것은@RequiredArgsConstructor
이렇게 하면 클래스 클래스가 항상 불변의 엔티티를 가진 컨스트럭터에만 의존할 수 있습니다.@AllArgsConstructor
을 사용하다
@AllArgsConstructor(suppressConstructorProperties = true)
을 사용하다의 정의lombok.anyConstructor.suppressConstructorProperties=true
(https://projectlombok.org/features/configuration)에서 POJO의 롬복 주석을 변경합니다.@Value
로로 합니다.@Data
+@NoArgsConstructor
+@AllArgsConstructor
잘 먹히네요.
1.4 lombok 1.18.4에 되는 주석을 구성할 수 있습니다. 해서 이걸 ㅇㅇㅇㅇㅇㅇㅇㅇㅇㅇ에 넣어주세요.
lombok.config
:lombok.copyableAnnotations += com.fasterxml.jackson.annotation.JsonProperty
그냥 '아까'를 붙이면 돼요.
@JsonProperty
다음 중 하나:...
이름이 일치하더라도 모든 필드에 @JsonProperty가 필요하지만, 이는 어쨌든 따르는 것이 좋습니다.또한 이를 사용하여 필드를 퍼블릭 파이널로 설정할 수 있습니다.게터보다 이 필드를 더 선호합니다.
@ToString
@EqualsAndHashCode
@Wither
@AllArgsConstructor(onConstructor=@__(@JsonCreator))
public class TestFoo {
@JsonProperty("xoom")
public final String x;
@JsonProperty("z")
public final int z;
}
단, getters(+setters)에서도 동작합니다.
롬복 버전을 'org.projectlombok:lombok:1.18.0'으로 업데이트 했을 때 동작했습니다.
이 롬복 주석을 사용하여 클래스를 불변하게 유지하고 역직렬화 할 수 있었습니다.
@NoArgsConstructor(force = true)
"믹신" 패턴을 사용하면 잭슨이 어떤 것이든 가지고 놀 수 있습니다.기본적으로 잭슨 주석을 기존 클래스에 추가할 때 클래스를 실제로 변경하지 않아도 됩니다.Rombok 솔루션보다는 이 솔루션을 추천하는 것이 Jackson의 기능에서 발생하는 문제를 해결했기 때문에 장기간에 걸쳐 기능할 가능성이 높기 때문에 이 솔루션을 추천하는 것이 좋습니다.
모든 수업에서 다음과 같은 주석을 달았습니다.
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@Data
@Accessors(fluent = true)
@NoArgsConstructor
@AllArgsConstructor
롬복과 잭슨의 모든 버전에서 최소 몇 년 동안 작동했습니다.
예:
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@Data
@Accessors(fluent = true)
@NoArgsConstructor
@AllArgsConstructor
public class Person {
String id;
String first;
String last;
}
그리고 이것이 마지막입니다.롬복과 잭슨은 부적처럼 함께 논다.
Gson을 사용하는 것은 번거롭지 않기 때문에 추천합니다.
스프링 부트 앱에 추가했습니다.
spring.mvc.converters.preferred-json-mapper=gson
메이븐의 의존성과 함께 모든 문제를 해결했습니다.나는 롬복 주석 포조스를 수정할 필요가 없었다.
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
public class Person {
String id;
String first;
String last;
}
데이터 클래스 외에 ObjectMapper를 올바르게 구성해야 합니다.이 경우 ParameterNamesModule 설정으로 정상적으로 동작하며 필드 및 Creator 메서드의 가시성을 설정합니다.
om.registerModule(new ParameterNamesModule());
om.setVisibility(FIELD, JsonAutoDetect.Visibility.ANY);
om.setVisibility(CREATOR, JsonAutoDetect.Visibility.ANY);
그럼 예상대로 되겠네요.
이 Lombok을 하지 않도록 데 .ConstructorProperies
어노테이션은 반대로 되어 잭슨이 그 어노테이션을 볼 수 없게 되었다.
범인은 Jackson Annotation입니다.내성자님.find Creator Annotation 입니다.주의:
if (_cfgConstructorPropertiesImpliesCreator
&& config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES)
Jackson Annotation도 주의해 주세요.내성자님.setConstructorPropertiesImpliesCreator:
public JacksonAnnotationIntrospector setConstructorPropertiesImpliesCreator(boolean b)
{
_cfgConstructorPropertiesImpliesCreator = b;
return this;
}
두 옵션 중 할 수 .MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
를 JacksonAnnotationIntrospector
설정하다setConstructorPropertiesImpliesCreator
로로 합니다.false
설정해 주세요.AnnotationIntrospector
ObjectMapper
오브젝트 맵퍼 경유.set 주석내성자님.
Jackson 8., 그 에서는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.잭슨 2.8.10입니다.MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
을 사용하다나는 그것이 잭슨의 어떤 버전에서 추가되었는지 확실하지 않다.없는 경우에는 '아예'를 합니다.JacksonAnnotationIntrospector.setConstructorPropertiesImpliesCreator
메카니즘.
이 모듈도 필요합니다.https://github.com/FasterXML/jackson-modules-java8
그런 다음 컴파일러의 -parameters 플래그를 켭니다.
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
저도 잠시 고생했어요.그러나 이 문서를 보면 onConstructor 주석 파라미터는 실험적인 것으로 간주되며 IDE(STS 4)에서는 잘 지원되지 않습니다.잭슨 문서에 따르면 개인 구성원은 기본적으로 직렬화되지 않습니다.이 문제를 신속하게 해결할 수 있는 방법이 있습니다.
JsonAutoDetect 주석을 추가하고 보호된 멤버/개인 멤버를 감지하도록 적절하게 설정합니다.이것은 DTO에게 편리합니다.
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class SomeClass
@JsonCreator 주석을 사용하여 공장 함수를 추가합니다. 이 기능은 객체 검증 또는 추가 변환이 필요한 경우에 가장 적합합니다.
public class SomeClass {
// some code here
@JsonCreator
public static SomeClass factory(/* params here dressing them in @JsonProperty annotations*/) {
return new SomeClass();
}
}
물론 직접 컨스트럭터를 추가할 수도 있습니다.
나에게 효과가 있는 옵션
- 콩에 @AllArgsConstructor를 넣는 것만으로 효과가 있었습니다.
- mapper.configure(MapperFeature)를 추가합니다.ACCEPT_CASE_INSECTIVE_PROPERTIES, true). 오브젝트 매퍼 인스턴스.
나는 다른 문제를 가지고 있었는데 그것은 부울 프리미티브 타입에 관한 것이었다.
private boolean isAggregate;
그 결과 다음과 같은 오류가 발생했습니다.
Exception: Unrecognized field "isAggregate" (class
이 Lambok을 변환합니다.isAggregate
로로 합니다.isAggregate()
로서 롬복의 내부 재산을 만드는 게터로서aggregate
, ★★★★★★★★★★★★★★★★」isAggregate
잭슨 도서관이 싫어해서isAggregate
대신 속성을 지정합니다.
이 문제를 해결하기 위해 원시 부울을 래퍼 부울로 업데이트했습니다.에도 이 문제를 다룰 때는 가지 이 있습니다.boolean
types 를 해 주세요types, "types" 를 해 주세요.
솔:
private Boolean isAggregate;
참조: https://www.baeldung.com/lombok-getter-boolean
언급URL : https://stackoverflow.com/questions/39381474/cant-make-jackson-and-lombok-work-together
'programing' 카테고리의 다른 글
useEffect 후크 내부의 상태를 설정할 수 있습니까? (0) | 2022.10.27 |
---|---|
반응: 컴포넌트 함수 내에 "this"가 정의되어 있지 않습니다. (0) | 2022.10.27 |
JavaScript 개체의 내용을 인쇄하시겠습니까? (0) | 2022.10.27 |
잘못된 날짜/시간 형식: 1366 잘못된 문자열 값 (0) | 2022.10.27 |
VueJ를 사용하여 테이블에 JSON 객체 표시s (0) | 2022.10.27 |