나는 Jackson과 Lombok을 결합하는 실험을하고 있습니다. 내 수업은 다음과 같습니다.
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)
-
Jackson 주석 : 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
-
Jackson databind : http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.8.2/jackson-databind-2.8.2.jar
-
Jackson-lombok : http://repo1.maven.org/maven2/io/paradoxical/jackson-lombok/1.1/jackson-lombok-1.1.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입니다. 내 Netbeans는 8.1입니다.
내 프로젝트가 잘 컴파일됩니다. 그러나 실행시 예외가 발생합니다. 예외는 쉽게 보이거나 명백하게 고칠 수있는 것 같지 않습니다. 다음은 stacktrace를 포함한 출력입니다.
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
주석으로 무작위로 찌르려고 시도했지만 더 나아질 수 없었습니다.
나는 예외를 봤고 jackson에 대한 오래된 버그 보고서 와 열려 있지만 다른 것과 관련된 것으로 보이는 다른 버그 보고서를 발견했습니다 . 그러나 이것은 여전히이 버그가 무엇인지 또는 수정 방법에 대해 알려주지 않습니다. 또한 다른 곳에서 유용한 것을 찾을 수 없었습니다.
내가하려는 것은 lombok과 jackson의 매우 기본적인 사용법이기 때문에이 문제를 해결하는 방법에 대한 유용한 정보를 더 이상 찾을 수 없다는 것이 이상하게 보입니다. 내가 뭔가를 놓친 것일까?
” 롬복을 사용하지 마십시오 “또는 ” 잭슨을 사용하지 마십시오 ” 라고 말하는 것 외에 ,이 문제를 해결하는 방법에 대해 아는 사람이 있습니까?
답변
불변하지만 lombok과 jackson을 사용하는 json 직렬화 가능한 POJO를 원한다면. 롬복 빌더에서 jacksons 새 주석을 사용하십시오. @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
어노테이션이 있는 빈 빌더 클래스를 제거 할 수 있습니다 .
답변
Immutable + Lombok + Jackson은 다음 방법으로 달성 할 수 있습니다.
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;
}
답변
나는 suppressConstructorProperties = true
매개 변수 를 추가하여 (귀하의 예를 사용하여) 똑같은 문제를 “해결”했습니다 .
@Value
@Wither
@AllArgsConstructor(suppressConstructorProperties = true)
public class TestFoo {
@JsonProperty("xoom")
private String x;
private int z;
}
Jackson은 분명히 java.beans.ConstructorProperties
생성자에 추가 된 주석을 좋아하지 않습니다 . suppressConstructorProperties = true
매개 변수는 말한다 롬복을 (그것이 기본적으로 수행)을 추가 할 수 없습니다.
답변
@AllArgsConstructor(suppressConstructorProperties = true)
더 이상 사용되지 않습니다. lombok.anyConstructor.suppressConstructorProperties=true
( https://projectlombok.org/features/configuration )을 정의 하고 POJO의 롬복 주석 @Value
을 @Data
+ @NoArgsConstructor
+로 변경 @AllArgsConstructor
하십시오.
답변
나를 위해 lombok 버전을 ‘org.projectlombok : lombok : 1.18.0’으로 업데이트했을 때 작동했습니다.
답변
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;
}
그래도 getter (+ setters)에서도 작동합니다.