Cara menentukan jackson untuk hanya menggunakan bidang - lebih disukai secara global

192

Perilaku jackon default tampaknya menggunakan kedua properti (getter dan setter) dan bidang untuk membuat cerita bersambung dan melakukan deserialisasi ke json.

Saya ingin menggunakan bidang sebagai sumber kan konfigurasi serialisasi dan karena itu tidak ingin jackson melihat properti sama sekali.

Saya bisa melakukan ini berdasarkan kelas individu dengan anotasi:

 @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)

Tapi saya tidak mau harus meletakkan ini di setiap kelas ...

Apakah mungkin untuk mengkonfigurasi ini secara global? Suka menambahkan beberapa ke Object Mapper?

Michael Wiles
sumber
1
Tim memberikan jawaban yang bagus. Kemungkinan lain adalah bahwa jika Anda memiliki kelas dasar yang sama, Anda dapat menempatkan anotasi kelas ke kelas itu; anotasi diwarisi oleh Jackson.
StaxMan
1
Saya pikir saya sudah mencobanya, tetapi sepertinya Anda harus memberi tahu sub kelas untuk menggunakan apa yang didefinisikan oleh kasus dasar ...
Michael Wiles
2
Tidak, kecuali sub-kelas mengabaikan anotasi kelas, anotasi orang tua terlihat seolah-olah mereka adalah bagian dari definisi sub-kelas (jika tidak, ini akan menjadi bug). Ini tidak selalu bagaimana JDK berurusan dengan anotasi, tetapi Jackson menerapkan pewarisan penuh untuk anotasi (bahkan untuk anotasi metode).
StaxMan
Waspadai INFER_PROPERTY_MUTATORSbendera. Ini memaksa visibilitas setter jika ada pengambil atau bidang yang terlihat.
Ondra Žižka
Dan lainnya .
Ondra Žižka

Jawaban:

157

Anda bisa mengonfigurasi ObjectMappers individual seperti ini:

ObjectMapper mapper  = new ObjectMapper();
mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()
                .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));

Jika Anda ingin mengaturnya secara global, saya biasanya mengakses mapper yang dikonfigurasi melalui kelas wrapper.

Tim Helmstedt
sumber
3
Bagus, meskipun saya pikir Anda mungkin perlu juga mengatur pemeriksa (withXxx () metode biasanya membuat objek baru). Jadi sesuatu seperti 'mapper.setVisibilityChecker (mapper.getVisibilityChecker (). Dengan ...);'
StaxMan
@StaxMan panggilan yang baik pada setVisibilityChecker, saya mengedit jawaban untuk mencerminkan.
Kevin Bowersox
42
withGetterVisibilitytidak membahas is*metode, tetapi ada withIsGetterVisibilityuntuk mereka.
qerub
13
setVisibilityCheckersudah ditinggalkan. Gunakan setVisibilitysebagai gantinya.
0x7d7b
1
Inilah yang saya butuhkan! Konfigurasi ini memungkinkan saya untuk menggunakan Mixin untuk dengan mudah mengkonversi entitas Hibernate ke DTO. Secara default ObjectMapper membuat serialisasi segalanya dan Mixin harus menentukan properti mana yang harus diabaikan (yaitu pengurangan alih-alih persimpangan).
TastyWheat
150

Di Jackson 2.0 dan yang lebih baru, Anda cukup menggunakan:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;   

...

ObjectMapper mapper = new ObjectMapper();    
mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

untuk mematikan deteksi otomatis.

lukk
sumber
1
Hai teman-teman, saya menggunakan stoples Jackson 1.9.0. Saya mendapatkan properti json tambahan, sementara objek bersambung ke string json. Saya perlu mendapatkan string json, yang hanya berisi variabel yang disebutkan dengan @JsonProperty. Bisakah Anda membantu saya dalam hal ini?
jrhamza
7
Anda dapat mulai dengan anotasi kelas yang disebutkan dalam pertanyaan OP: @JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)Selanjutnya, Anda harus memberi anotasi pada setiap properti yang ingin Anda sertakan dengan@JsonProperty
lukk
Terima kasih! Sebelumnya, saya telah menemukan banyak contoh kode di mana JsonMethod direferensikan alih-alih PropertyAccessor. Jika Anda mencari JsonMethod, Anda jarang mendapatkan tautan ke PropertyAccessor lalu ... Apa cara terbaik untuk menemukan nama kelas pengganti di artefak penerus? Bisa jadi tangguh dan jahat, bukan?
philburns
38

Khusus untuk boolean is*()getter:

Saya telah menghabiskan banyak waktu untuk alasan mengapa tidak ada di bawah ini

  @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)

atau ini

  setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE);
  setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);
  setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

bekerja untuk Boolean Getter / Setter saya.

Solusinya sederhana:

  @JsonAutoDetect(isGetterVisibility = Visibility.NONE, ...          
  setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);

UPDATE: spring-boot diizinkan konfigurasikan:

jackson:
  visibility.field: any
  visibility.getter: none
  visibility.setter: none
  visibility.is-getter: none

Lihat Properti aplikasi umum # JACKSON

Grigory Kislin
sumber
1
Bisakah Anda menguraikan bagaimana solusi sederhana harus diterapkan pada kelas bean?
Pavel Niedoba
1
Terima kasih. Itu IsGetter menyelamatkan hari untukku.
Grinch
Ini bukan jawaban untuk pertanyaan dan agak menyesatkan.
Ondra Žižka
14

untuk jackson 1.9.10 saya gunakan

ObjectMapper mapper = new ObjectMapper();

mapper.setVisibility(JsonMethod.ALL, Visibility.NONE);
mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);

untuk mematikan pemotongan otomatis.

mfe
sumber
2
Itulah caranya. Terima kasih.
cuneytykaya
bertanya-tanya apakah ada perbedaan antara melakukan ini dan menonaktifkan "deteksi otomatis".
xenoterracide
10

Bagaimana dengan ini: Saya menggunakannya dengan mixin

objek tidak sesuai

@Entity
@Getter
@NoArgsConstructor
public class Telemetry {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long pk;
    private String id;
    private String organizationId;
    private String baseType;
    private String name;
    private Double lat;
    private Double lon;
    private Instant updateTimestamp;
}

Mixin:

@JsonAutoDetect(fieldVisibility = ANY, getterVisibility = NONE, setterVisibility = NONE)
public static class TelemetryMixin {}

Pemakaian:

    ObjectMapper om = objectMapper.addMixIn(Telemetry.class, TelemetryMixin.class);
    Telemetry[] telemetries = om.readValue(someJson, Telemetry[].class);

Tidak ada yang mengatakan Anda tidak dapat melakukan prakiraan jumlah kelas dan menerapkan mixin yang sama.

Jika Anda tidak terbiasa dengan mixin, mereka secara konseptual sederhana: Struktur mixin super dipaksakan pada kelas target (menurut jackson, tidak sejauh yang menyangkut JVM).

Christian Bongiorno
sumber
3

Jika Anda ingin cara untuk melakukan ini secara global tanpa khawatir tentang konfigurasi Anda ObjectMapper, Anda dapat membuat anotasi sendiri:

@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonAutoDetect(
        getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE,
        setterVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.NONE,
        creatorVisibility = JsonAutoDetect.Visibility.NONE
)
public @interface JsonExplicit {
}

Sekarang Anda hanya perlu membubuhi keterangan kelas @JsonExplicitAnda dan Anda baik-baik saja!

Pastikan juga untuk mengedit panggilan di atas @JsonAutoDetectuntuk memastikan Anda memiliki nilai yang ditetapkan untuk apa yang bekerja dengan program Anda.

Kredit untuk https://stackoverflow.com/a/13408807 untuk membantu saya mencari tahu@JacksonAnnotationsInside

retodaredevil
sumber
3

Jika Anda menggunakan Spring Boot, Anda dapat mengonfigurasi Jackson secara global sebagai berikut:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonObjectMapperConfiguration implements Jackson2ObjectMapperBuilderCustomizer {

    @Override
    public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY);
    }

}

Waktu
sumber