Bagaimana cara memberitahu Jackson untuk mengabaikan bidang selama serialisasi jika nilainya nol?

687

Bagaimana Jackson dapat dikonfigurasi untuk mengabaikan nilai bidang selama serialisasi jika nilai bidang itu nol.

Sebagai contoh:

public class SomeClass {
   // what jackson annotation causes jackson to skip over this value if it is null but will 
   // serialize it otherwise 
   private String someValue; 
}
am
sumber

Jawaban:

1102

Untuk menekan properti serialisasi dengan nilai nol menggunakan Jackson> 2.0, Anda dapat mengonfigurasi ObjectMappersecara langsung , atau memanfaatkan @JsonIncludeanotasi:

mapper.setSerializationInclusion(Include.NON_NULL);

atau:

@JsonInclude(Include.NON_NULL)
class Foo
{
  String bar;
}

Atau, Anda bisa menggunakan @JsonInclude dalam pengambil sehingga atribut akan ditampilkan jika nilainya tidak nol.

Contoh yang lebih lengkap tersedia dalam jawaban saya untuk Bagaimana mencegah nilai nol di dalam Peta dan bidang nol di dalam kacang menjadi serial melalui Jackson .

Programmer Bruce
sumber
81
untuk proyek saya, ini berhasil @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL):; entah bagaimana anotasi Anda tidak tersedia.
Emmanuel Touzery
13
API berubah sedikit dengan rilis 2.0.
Programmer Bruce
10
@ProgrammerBruce -1 ubah jawaban Anda karena Anda menyadari perubahan itu.
Martin Asenov
19
Ya, saya baru saja mengkonfirmasi bahwa @JsonIncludenotasi tidak berfungsi, tetapi ini berfungsi seperti pesona: @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) (Saya menggunakan Jackson 1.9.12 dengan Spring 3.2.2.)
gstroup
17
@ MartinAsenov - jawabannya menunjukkan API terbaru; itu diubah dari @JsonSerializesintaks ke @JsonInclude. Sintaks yang lebih lama tidak digunakan lagi.
Logan Pickup
128

Dengan Jackson> 1.9.11 dan <2.x gunakan @JsonSerializeanotasi untuk melakukan itu:

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

WTK
sumber
10
Saat ini (Jackson 2.x) pendekatan ini sudah usang.
rustyx
39
@JsonInclude (JsonInclude.Include.NON_NULL)
ZiglioUK
3
@JsonSerialize(using = FooSerializer.class, include = JsonSerialize.Inclusion.NON_NULL)tidak bekerja nilai nullable diserialisasi.
herau
1
Sudah usang tetapi jika Anda perlu mempertahankan hal-hal lama jawaban ini benar-benar baik-baik saja! jadi terima kasih @WTK :)
DominikAngerer
Sebagai catatan tambahan, Jackson 1.9.12 adalah standar di WebSphere 8.5, semoga info ini akan menghemat banyak waktu bagi orang lain untuk mengetahui hal ini :-)
bakoyaro
122

Hanya untuk memperluas jawaban lain - jika Anda perlu mengontrol kelalaian nilai nol pada basis per-bidang, beri anotasi bidang yang dimaksud (atau anotasi 'pengambil' bidang tersebut).

contoh - di sini hanya fieldOneakan dinonaktifkan dari json jika itu nol. fieldTwoakan selalu disertakan terlepas dari apakah itu nol.

public class Foo {

    @JsonInclude(JsonInclude.Include.NON_NULL) 
    private String fieldOne;

    private String fieldTwo;
}

Untuk menghilangkan semua nilai nol di kelas sebagai default, beri catatan kelas. Anotasi per bidang / pengambil masih dapat digunakan untuk menimpa default ini jika perlu.

contoh - di sini fieldOnedan fieldTwoakan dihapus dari json jika masing-masing adalah nol, karena ini adalah default yang ditetapkan oleh anotasi kelas. fieldThreeNamun akan menimpa default dan akan selalu dimasukkan, karena penjelasan di lapangan.

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Foo {

    private String fieldOne;

    private String fieldTwo;

    @JsonInclude(JsonInclude.Include.ALWAYS)
    private String fieldThree;
}

MEMPERBARUI

Di atas adalah untuk Jackson 2 . Untuk versi Jackson sebelumnya, Anda perlu menggunakan:

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) 

dari pada

@JsonInclude(JsonInclude.Include.NON_NULL)

Jika pembaruan ini bermanfaat, harap jawab jawaban ZiglioUK di bawah ini, ini menunjukkan anotasi Jackson 2 yang baru jauh sebelum saya memperbarui jawaban saya untuk menggunakannya!

davnicwil
sumber
bukankah seharusnya anotasi di lapangan SELALU ditimpa?
Abhinav Vishak
@AbhinavVishak Anda benar - terima kasih! Itu salah salin-tempel ketika saya memperbarui jawaban untuk menggunakan Jackson 2. Diedit.
davnicwil
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) sudah ditinggalkan
Yar
1
@Ya ya, itu sudah usang di Jackson 2.x. Saya telah menyatakan bahwa Anda perlu menggunakannya hanya di versi Jackson yang lebih lama di mana tidak hanya itu tidak usang, itu satu-satunya pilihan.
davnicwil
60

Di Jackson 2.x, gunakan:

@JsonInclude(JsonInclude.Include.NON_NULL)
ZiglioUK
sumber
apakah ini untuk ditempatkan di lapangan.
pagi
1
@ ya ampun, anotasi ini harus membungkus kelas
Edgard Leal
Bisakah Anda juga memasukkan nama yang sepenuhnya memenuhi syarat? Jackson memiliki banyak anotasi dengan nama yang sama dan paket yang berbeda, sehingga ambigu.
Vince
maksud Anda ada beberapa anotasi @JsonInclude di Jackson? Saya tidak tahu. Apa nama yang harus memenuhi syarat itu? jangan ragu untuk mengedit jawabannya
ZiglioUK
Kebingungan dengan nama kemungkinan besar disebabkan oleh Jackson 1.x dan 2.x menggunakan paket Java yang berbeda untuk semuanya, untuk menghindari konflik loader kelas (wrt versi kelas yang tidak kompatibel). Karena jawaban ini untuk 2.x, paket untuk anotasi adalah com.fasterxml.jackson.annotation- Jackson 1.x hadorg.codehaus.jackson.annoation
StaxMan
39

Anda dapat menggunakan konfigurasi mapper berikut:

mapper.getSerializationConfig().setSerializationInclusion(Inclusion.NON_NULL);

Sejak 2,5 Anda dapat pengguna:

mapper.setSerializationInclusion(Include.NON_NULL);
Eren Yilmaz
sumber
3
Karena ini tidak digunakan lagi pada 1.9, gunakan mapper.getSerializationConfig (). WithSerializationInclusion (JsonSerialize.Inclusion.NON_NULL);
Asa
7
..atau langsung: mapper.setSerializationInclusion (NON_NULL);
Asa
@ruslan: Mungkin karena dokumentasi getSerializationConfig() mengatakan:Note that since instances are immutable, you can NOT change settings by accessing an instance and calling methods: this will simply create new instance of config object.
Zero3
Untuk penggunaan 2.5.4mapper.setSerializationInclusion(Include.NON_NULL);
Arturo Volpe
12

dalam hal ini

@JsonInclude(Include.NON_EMPTY)

membuatnya bekerja.

alfthan
sumber
2
NON_EMPTY agak berbeda dari NON_NULL - itu akan mengabaikan nilai nol, itu benar, tetapi juga akan mengabaikan nilai yang dianggap kosong, yang mungkin bukan perilaku yang diinginkan. Lihat javadocs Jackson untuk info lebih lanjut
davnicwil
Saya suka jawaban ini karena mengembalikan Opsional dari hal-hal yang benar-benar opsional adalah ide yang baik, dan hanya dengan NON_NULL Anda akan mendapatkan sesuatu seperti { }untuk null, yang tanpa tujuan mentransfer idiom Java ke konsumen. sama dengan AtomicReference - konsumen tidak peduli bagaimana pengembang memilih untuk menegakkan keamanan utas pada representasi internal dari respons.
Lucas Ross
8
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonInclude(JsonInclude.Include.NON_EMPTY)

harus bekerja.

Include.NON_EMPTYmenunjukkan bahwa properti diserialisasi jika nilainya tidak nol dan tidak kosong. Include.NON_NULLmenunjukkan bahwa properti diserialisasi jika nilainya tidak nol.

Neha Gangwar
sumber
2
JsonInclude.Include.NON_EMPTY- sudah cukup karena mencakup kasus NOT_NULL
Ilya Buziuk
5

Jika Anda ingin menambahkan aturan ini ke semua model di Jackson 2.6+ gunakan:

mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
Ilia Kurtov
sumber
5

Jika di Spring Boot , Anda dapat menyesuaikan jackson ObjectMappersecara langsung melalui file properti.

Contoh application.yml:

spring:
  jackson:
    default-property-inclusion: non_null # only include props if non-null

Nilai yang mungkin adalah:

always|non_null|non_absent|non_default|non_empty

Lebih lanjut: https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper

acdcjunior
sumber
5

Ini akan bekerja di Spring boot 2.0.3+ dan Jackson 2.0+

import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiDTO
{
    // your class variable and 
    // methods
}
Deva
sumber
1
Hal yang sama berlaku @JsonInclude(JsonInclude.Include.NON_NULL)bagi saya pada boot Musim Semi 2.1.2 dan anotasi Jackson 2.9.0
manasouza
@manasouza Ya, mereka mempertahankan konsistensi untuk semua pembaruan.
Deva
3

Untuk penggunaan Jackson 2.5:

@JsonInclude(content=Include.NON_NULL)
Bilal BBB
sumber
2

Ini telah mengganggu saya selama beberapa waktu dan akhirnya saya menemukan masalahnya. Masalahnya adalah karena impor yang salah. Sebelumnya saya telah menggunakan

com.fasterxml.jackson.databind.annotation.JsonSerialize

Yang sudah usang. Cukup ganti impor dengan

import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;

dan gunakan sebagai

@JsonSerialize(include=Inclusion.NON_NULL)
pengguna3443646
sumber
2

Konfigurasi global jika Anda menggunakan Spring

@Configuration
public class JsonConfigurations {

    @Bean
    public Jackson2ObjectMapperBuilder objectMapperBuilder() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.serializationInclusion(JsonInclude.Include.NON_NULL);
        builder.serializationInclusion(JsonInclude.Include.NON_EMPTY);
        builder.failOnUnknownProperties(false);
        return builder;
    }

}
Xelian
sumber
Pengaturan serializationInclusion tidak menambahkan satu sama lain. public Jackson2ObjectMapperBuilder serializationInclusion(JsonInclude.Include serializationInclusion) { this.serializationInclusion = serializationInclusion; return this; }; Seseorang harus menggunakan radius enumerasi inklusi yang lebih besar. mis. NON_ABSENT termasuk NON_NULL dan NON_EMPTY termasuk keduanya. Karena itu, seharusnya hanya builder.serializationInclusion(JsonInclude.Include.NON_EMPTY); JacksonInclude doc
Olgun Kaya
2

Jika Anda mencoba membuat serial daftar objek dan salah satunya adalah nol, Anda akan berakhir dengan memasukkan item nol di JSON bahkan dengan

mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

akan menghasilkan:

[{myObject},null]

untuk mendapatkan ini:

[{myObject}]

seseorang dapat melakukan sesuatu seperti:

mapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
        @Override
        public void serialize(Object obj, JsonGenerator jsonGen, SerializerProvider unused)
                throws IOException
        {
            //IGNORES NULL VALUES!
        }
    });

TIP: Jika Anda menggunakan DropWizard, Anda dapat mengambil yang ObjectMappersedang digunakan oleh Jersey menggunakanenvironment.getObjectMapper()

pengguna3474985
sumber
1

Kami memiliki banyak jawaban untuk pertanyaan ini. Jawaban ini mungkin membantu dalam beberapa skenario. Jika Anda ingin mengabaikan nilai nol, Anda dapat menggunakan NOT_NULL di tingkat kelas. seperti di bawah ini

@JsonInclude(Include.NON_NULL)
class Foo
{
  String bar;
}

Beberapa kali Anda mungkin perlu mengabaikan nilai kosong seperti Anda mungkin telah menginisialisasi arrayList tetapi tidak ada elemen dalam daftar itu. Pada waktu itu menggunakan NOT_EMPTY anotasi untuk mengabaikan bidang nilai kosong itu

@JsonInclude(Include.NON_EMPTY)
class Foo
{
  String bar;
}

sumber
0

Jackson 2.x + digunakan

mapper.getSerializationConfig().withSerializationInclusion(JsonInclude.Include.NON_NULL);
mekdev
sumber
.withSerializationInclusion(JsonInclude.Include.NON_NULL)bukan kan?
herau
Terima kasih telah menunjukkan hal itu, saya akan menunda untuk memutakhirkan :-(
ZiglioUK
@ruslan: Mungkin karena dokumentasi getSerializationConfig()mengatakan:Note that since instances are immutable, you can NOT change settings by accessing an instance and calling methods: this will simply create new instance of config object.
Zero3
0

Juga, Anda harus mengubah pendekatan Anda saat menggunakan Map myVariable seperti yang dijelaskan dalam dokumentasi untuk menghilangkan nulls:

From documentation:
com.fasterxml.jackson.annotation.JsonInclude

@JacksonAnnotation
@Target(value={ANNOTATION_TYPE, FIELD, METHOD, PARAMETER, TYPE})
@Retention(value=RUNTIME)
Annotation used to indicate when value of the annotated property (when used for a field, method or constructor parameter), or all properties of the annotated class, is to be serialized. Without annotation property values are always included, but by using this annotation one can specify simple exclusion rules to reduce amount of properties to write out.

*Note that the main inclusion criteria (one annotated with value) is checked on Java object level, for the annotated type, and NOT on JSON output -- so even with Include.NON_NULL it is possible that JSON null values are output, if object reference in question is not `null`. An example is java.util.concurrent.atomic.AtomicReference instance constructed to reference null value: such a value would be serialized as JSON null, and not filtered out.

To base inclusion on value of contained value(s), you will typically also need to specify content() annotation; for example, specifying only value as Include.NON_EMPTY for a {link java.util.Map} would exclude Maps with no values, but would include Maps with `null` values. To exclude Map with only `null` value, you would use both annotations like so:
public class Bean {
   @JsonInclude(value=Include.NON_EMPTY, content=Include.NON_NULL)
   public Map<String,String> entries;
}

Similarly you could Maps that only contain "empty" elements, or "non-default" values (see Include.NON_EMPTY and Include.NON_DEFAULT for more details).
In addition to `Map`s, `content` concept is also supported for referential types (like java.util.concurrent.atomic.AtomicReference). Note that `content` is NOT currently (as of Jackson 2.9) supported for arrays or java.util.Collections, but supported may be added in future versions.
Since:
2.0
atom88
sumber
0

Kasus satu

@JsonInclude(JsonInclude.Include.NON_NULL)
private String someString;

Kasus dua

@JsonInclude(JsonInclude.Include.NON_EMPTY)
private String someString;

Jika someStringnol, itu akan diabaikan pada kedua kasus. Jika someString"" itu hanya diabaikan pada kasus dua.

Hal yang sama untuk List = nullatauList.size() = 0

Nguyen Minh Hien
sumber