Saya sedang bereksperimen dalam menggabungkan Jackson dan Lombok. Itu adalah kelasku:
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);
}
}
Itu adalah JAR yang saya tambahkan ke classpth:
Lombok: https://projectlombok.org/downloads/lombok.jar (versi 1.16.10)
Anotasi Jackson: http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.8.2/jackson-annotations-2.8.2.jar
Inti Jackson: 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
Saya mengompilasinya dengan Netbeans (menurut saya ini tidak benar-benar relevan, tetapi saya tetap melaporkannya agar dapat direproduksi dengan sempurna dan setia). Lima JAR di atas disimpan dalam folder bernama " lib
" di dalam folder proyek (bersama dengan " src
", " nbproject
", " test
" dan " build
"). Saya menambahkannya ke Netbeans melalui tombol " Tambahkan JAR / Folder " di properti proyek dan mereka terdaftar dalam urutan yang tepat seperti daftar di atas. Proyek ini adalah proyek jenis "aplikasi Java" standar.
Lebih lanjut, proyek Netbeans dikonfigurasi untuk " JANGAN dikompilasi saat disimpan ", " buat info debugging ", " laporkan API yang tidak digunakan lagi ", " lacak ketergantungan java ", " aktifkan pemrosesan anotasi ", dan " aktifkan pemrosesan anotasi di editor ". Tidak ada pemroses anotasi atau opsi pemrosesan anotasi yang dikonfigurasi secara eksplisit di Netbeans. Selain itu, -Xlint:all
opsi baris perintah " " diteruskan di baris perintah kompilator, dan kompilator dijalankan pada VM eksternal.
Versi javac saya adalah 1.8.0_72 dan versi java saya adalah 1.8.0_72-b15. Netbeans saya adalah 8.1.
Proyek saya terkompilasi dengan baik. Namun, itu membuat pengecualian dalam eksekusinya. Pengecualian tampaknya tidak menjadi sesuatu yang terlihat mudah atau jelas dapat diperbaiki. Berikut adalah outputnya, termasuk 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
Saya sudah mencoba mencolek secara acak dengan anotasi @Value
dan @AllArgsConstructor
, tetapi saya tidak bisa membuatnya lebih baik.
Saya mencari pengecualian di Google dan menemukan laporan bug lama tentang jackson , dan satu lagi yang terbuka, tetapi tampaknya terkait dengan sesuatu yang lain . Namun, ini masih tidak memberi tahu apa-apa tentang bug ini atau bagaimana cara memperbaikinya. Juga, saya tidak dapat menemukan sesuatu yang berguna mencari itu di tempat lain.
Karena apa yang saya coba lakukan adalah penggunaan yang sangat mendasar dari lombok dan jackson, tampaknya aneh bahwa saya tidak dapat menemukan informasi yang lebih berguna tentang cara mengatasi masalah ini. Mungkin saya melewatkan sesuatu?
Selain hanya mengatakan " jangan gunakan lombok " atau " jangan gunakan jackson ", apakah ada yang tahu tentang cara mengatasinya?
Immutable + Lombok + Jackson dapat dicapai dengan cara berikut:
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); } }
sumber
AllArgsConstructor
sudah menjadi bagian dari@Value
anotasi?@NoArgsConstructor
menimpa konstruktor yang dihasilkan oleh@Value
anotasi, jadi Anda harus menambahkan ekstra@AllArgsConstructor
Saya mencoba beberapa cara di atas dan semuanya temperamental. Apa yang benar-benar berhasil bagi saya adalah jawaban yang saya temukan di sini .
pada direktori root proyek Anda, tambahkan file lombok.config (jika Anda belum melakukannya)
dan di dalam tempel ini
lombok.anyConstructor.addConstructorProperties=true
Kemudian Anda dapat menentukan pojos Anda seperti berikut:
@Data @AllArgsConstructor public class MyPojo { @JsonProperty("Description") private String description; @JsonProperty("ErrorCode") private String errorCode; }
sumber
Saya mengalami masalah yang persis sama, "menyelesaikannya" dengan menambahkan
suppressConstructorProperties = true
parameter (menggunakan contoh Anda):@Value @Wither @AllArgsConstructor(suppressConstructorProperties = true) public class TestFoo { @JsonProperty("xoom") private String x; private int z; }
Jackson tampaknya tidak menyukai
java.beans.ConstructorProperties
penjelasan yang ditambahkan ke konstruktor. ThesuppressConstructorProperties = true
parameter memberitahu Lombok tidak menambahkannya (hal ini secara default).sumber
suppressConstructorProperties
sekarang tidak digunakan lagi :-(false
.@AllArgsConstructor(suppressConstructorProperties = true)
sudah ditinggalkan. Tentukanlombok.anyConstructor.suppressConstructorProperties=true
( https://projectlombok.org/features/configuration ) dan ubah anotasi lombok POJO dari@Value
menjadi@Data
+@NoArgsConstructor
+@AllArgsConstructor
berfungsi untuk saya.sumber
Bagi saya ini berhasil ketika saya telah memperbarui versi lombok ke: 'org.projectlombok: lombok: 1.18.0'
sumber
Dari Jawaban Jan Rieke
Anda akan membutuhkan @JsonProperty di setiap bidang meskipun namanya cocok, tetapi itu adalah praktik yang baik untuk diikuti. Anda juga dapat mengatur bidang Anda ke final publik menggunakan ini, yang saya lebih suka daripada getter.
@ToString @EqualsAndHashCode @Wither @AllArgsConstructor(onConstructor=@__(@JsonCreator)) public class TestFoo { @JsonProperty("xoom") public final String x; @JsonProperty("z") public final int z; }
Ini juga harus bekerja dengan getter (+ setter).
sumber
Can not deserialize instance of java.lang.String out of START_OBJECT token
... Dan ini memperbaikinya! Saya perlu memiliki@JsonProperty
anotasi itu untuk setiap parameter konstruktor dan tambahan itu ke@AllArgsConstructor
allow lombok ke instrumennya.Anda bisa membuat Jackson bermain dengan apa saja jika Anda menggunakan pola "mixin" . Pada dasarnya, ini memberi Anda cara untuk menambahkan anotasi Jackson ke kelas yang ada tanpa benar-benar memodifikasi kelas itu. Saya cenderung merekomendasikannya di sini daripada solusi Lombok karena ini memecahkan masalah yang dialami Jackson dengan fitur Jackson, jadi kemungkinan besar berfungsi dalam jangka panjang.
sumber
Saya semua kelas saya diberi keterangan seperti ini:
@JsonAutoDetect(fieldVisibility = Visibility.ANY) @JsonInclude(JsonInclude.Include.NON_DEFAULT) @Data @Accessors(fluent = true) @NoArgsConstructor @AllArgsConstructor
Ini bekerja dengan semua versi Lombok dan Jackson selama, setidaknya, beberapa tahun.
Contoh:
@JsonAutoDetect(fieldVisibility = Visibility.ANY) @JsonInclude(JsonInclude.Include.NON_DEFAULT) @Data @Accessors(fluent = true) @NoArgsConstructor @AllArgsConstructor public class Person { String id; String first; String last; }
Dan itu dia. Lombok dan Jackson bermain bersama seperti pesona.
sumber
@JsonInclude(JsonInclude.Include.NON_NULL) @Data public class Person { String id; String first; String last; }
Tambahan untuk Data Class, itu harus dikonfigurasi dengan benar ObjectMapper. Dalam hal ini, ini berfungsi dengan baik dengan konfigurasi ParameterNamesModule, dan pengaturan visibilitas Fields dan Metode Pembuat
om.registerModule(new ParameterNamesModule()); om.setVisibility(FIELD, JsonAutoDetect.Visibility.ANY); om.setVisibility(CREATOR, JsonAutoDetect.Visibility.ANY);
Maka itu harus bekerja seperti yang diharapkan.
sumber
Saya mengalami masalah dengan membuat Lombok tidak menambahkan
ConstructorProperies
anotasi, jadi pergi ke arah lain dan menonaktifkan Jackson dari melihat anotasi itu.Pelakunya adalah JacksonAnnotationIntrospector.findCreatorAnnotation . Memperhatikan:
if (_cfgConstructorPropertiesImpliesCreator && config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES)
Perhatikan juga JacksonAnnotationIntrospector.setConstructorPropertiesImpliesCreator :
public JacksonAnnotationIntrospector setConstructorPropertiesImpliesCreator(boolean b) { _cfgConstructorPropertiesImpliesCreator = b; return this; }
Jadi dua opsi, baik setel
MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
ke salah atau buat satuJacksonAnnotationIntrospector
setsetConstructorPropertiesImpliesCreator
kefalse
dan setel iniAnnotationIntrospector
keObjectMapper
via ObjectMapper.setAnnotationIntrospector .Perhatikan beberapa hal, saya menggunakan Jackson 2.8.10 dan dalam versi
MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
itu tidak ada. Saya tidak yakin versi Jackson mana yang ditambahkan. Jadi kalau tidak ada, pakaiJacksonAnnotationIntrospector.setConstructorPropertiesImpliesCreator
mekanismenya.sumber
Anda juga perlu memiliki modul ini. https://github.com/FasterXML/jackson-modules-java8
kemudian aktifkan tanda -parameters untuk kompilator Anda.
<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>
sumber
Saya berjuang dengan ini sejenak juga. Tetapi melihat melalui dokumentasi di sini saya dapat melihat bahwa parameter anotasi onConstructor dianggap eksperimental dan tidak didukung dengan baik di IDE saya (STS 4). Menurut dokumentasi Jackson, anggota pribadi tidak (de) diserialkan secara default. Ada cara cepat untuk mengatasinya.
Tambahkan anotasi JsonAutoDetect dan setel dengan tepat untuk mendeteksi anggota yang dilindungi / pribadi. Ini nyaman untuk DTO
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public class SomeClass
Tambahkan fungsi pabrik dengan anotasi @JsonCreator, ini bekerja paling baik jika Anda memerlukan beberapa validasi objek atau transformasi tambahan.
public class SomeClass { // some code here @JsonCreator public static SomeClass factory(/* params here dressing them in @JsonProperty annotations*/) { return new SomeClass(); } }
Tentu saja Anda juga dapat menambahkan konstruktor pada diri Anda sendiri secara manual.
sumber
Saya memiliki masalah yang berbeda dan itu dengan tipe primitif boolean.
private boolean isAggregate;
Akibatnya, muncul kesalahan berikut
Exception: Unrecognized field "isAggregate" (class
Lambok bertobat
isAggregate
untukisAggregate()
sebagai getter membuat properti internal lombok sebagaiaggregate
gantinyaisAggregate
. Perpustakaan Jackson tidak menyukainya dan ia membutuhkanisAggregate
properti sebagai gantinya.Saya memperbarui boolean primitif ke Wrapper Boolean untuk mengatasi masalah ini. Ada opsi lain untuk Anda jika Anda berurusan dengan
boolean
tipe, lihat referensi di bawah.Sol:
private Boolean isAggregate;
ref: https://www.baeldung.com/lombok-getter-boolean
sumber