Як сказати Джексону ігнорувати поле під час серіалізації, якщо його значення є нульовим?


687

Як Джексона можна налаштувати ігнорувати значення поля під час серіалізації, якщо значення цього поля є нульовим.

Наприклад:

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; 
}

Відповіді:


1102

Щоб придушити властивості серіалізації з нульовими значеннями за допомогою Jackson> 2.0, ви можете налаштувати ObjectMapperбезпосередньо або скористатися @JsonIncludeанотацією:

mapper.setSerializationInclusion(Include.NON_NULL);

або:

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

Крім того, ви можете використовувати @JsonIncludeв getter так, щоб атрибут відображався, якщо значення не є нульовим.

Більш повний приклад доступний у моїй відповіді на тему, як запобігти нульовим значенням усередині карти та нульовим полям у квасолі не отримати серіалізацію через Джексона .


81
для мого проекту це спрацювало @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL):; чомусь ваша примітка не була доступною.
Еммануель Тузері

13
API дещо змінився з випуском 2.0.
Програміст Брюс

11
@ProgrammerBruce -1 змінити відповідь відповідно, оскільки вам відомо про зміну.
Мартін Асенов

19
Так, я щойно підтвердив, що @JsonIncludeпозначення не працює, але це працює як принадність: @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) (Я використовую Джексона 1.9.12 з Spring 3.2.2.)
gstroup

17
@MartinAsenov - у відповіді показано найновіший API; це було змінено з @JsonSerializeсинтаксису на @JsonInclude. Старіший синтаксис застарілий.
Логан Пікап

128

Для Jackson> 1.9.11 та <2.x використовуйте @JsonSerializeдля цього примітки:

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)


10
На сьогоднішній день (Джексон 2.х) цей підхід застарів.
rustyx

39
@JsonInclude (JsonInclude.Include.NON_NULL)
ZiglioUK

3
@JsonSerialize(using = FooSerializer.class, include = JsonSerialize.Inclusion.NON_NULL)не працює. нульові значення серіалізуються.
herau

1
Це застаріло, але якщо вам потрібно зберегти старі речі, ця відповідь цілком чудова! тож дякую @WTK :)
DominikAngerer

Як зауваження, Джексон 1.9.12 є стандартним для WebSphere 8.5, сподіваємось, ця інформація заощадить комусь ще багато часу, що мені знадобилося це зрозуміти :-)
bakoyaro

122

Просто для розширення інших відповідей - якщо вам потрібно контролювати опущення нульових значень на основі кожного поля, анотуйте поле, про яке йдеться (або альтернативно анотуйте «гетьтер» поля).

приклад - тут fieldOneбуде опущено лише json, якщо він є нульовим. fieldTwoзавжди буде включено незалежно від того, чи недійсне воно.

public class Foo {

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

    private String fieldTwo;
}

Щоб опустити всі нульові значення класу за замовчуванням, анотуйте клас. Анотації за полем / геттером все ще можуть використовуватися для зміни цього за замовчуванням, якщо це необхідно.

Приклад - тут fieldOneі fieldTwoбуде опущено з json, якщо вони є нульовими, відповідно, тому що це типово встановлений анотацією класу. fieldThreeоднак буде замінено за замовчуванням і завжди буде включено через анотацію на полі.

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

    private String fieldOne;

    private String fieldTwo;

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

ОНОВЛЕННЯ

Сказане вище для Джексона 2 . Для більш ранніх версій Jackson вам потрібно використовувати:

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) 

замість

@JsonInclude(JsonInclude.Include.NON_NULL)

Якщо це оновлення корисне, будь ласка, підкажіть відповідь ZiglioUK нижче, воно вказувало на новіші анотації Jackson 2 задовго до того, як я оновив свою відповідь, щоб використовувати її!


чи не слід анотацію на полі ЗАВЖДИ перекривати?
Абхінав Вішак

@AbhinavVishak ви праві - дякую! Це була помилка копіювання та вставки, коли я оновив відповідь на використання Джексона 2. Відредаговано.
davnicwil

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) засуджується
Яра

1
@Yar так, це застаріло в Джексоні 2.x. Я сказав , що ви повинні використовувати це тільки в більш ранніх версіях Джексона , де не тільки він НЕ осуджені, це єдиний варіант.
davnicwil

60

У Джексоні 2.x використовуйте:

@JsonInclude(JsonInclude.Include.NON_NULL)

це потрібно розмістити на полі.
Ams

1
@ams, ця анотація повинна містити клас
Едгард Ліл

Чи можете ви також включити повноцінне ім’я? У Джексона є кілька анотацій з тим же ім'ям та різним пакетом, тому це неоднозначно.
Вінс

Ви кажете, що у Джексона є кілька приміток @JsonInclude? Я поняття не мав. Яким має бути тоді повноцінне ім’я? не соромтесь редагувати відповідь
ZiglioUK

Плутанина з іменами, швидше за все, пов’язана з тим, що Jackson 1.x і 2.x використовує різні пакети Java для всього, щоб уникнути конфліктів завантажувачів класів (wrt несумісні версії класів). Оскільки ця відповідь стосується 2.x, пакет анотацій буде com.fasterxml.jackson.annotation- Джексон 1.x мавorg.codehaus.jackson.annoation
StaxMan

39

Ви можете використовувати таку конфігурацію картографів:

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

З 2,5 року ви можете користуватися:

mapper.setSerializationInclusion(Include.NON_NULL);

3
Оскільки це застаріло в 1.9, використовуйте mapper.getSerializationConfig (). WithSerializationInclusion (JsonSerialize.Inclusion.NON_NULL);
Аса

7
.. або безпосередньо: mapper.setSerializationInclusion (NON_NULL);
Аса

@ruslan: Мабуть тому, що в документації getSerializationConfig() написано: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

Для використання 2.5.4mapper.setSerializationInclusion(Include.NON_NULL);
Артуро Вольпе


12

в моєму випадку

@JsonInclude(Include.NON_EMPTY)

змусив це працювати.


2
NON_EMPTY тонко відрізняється від NON_NULL - він буде ігнорувати нульові значення, це правда, але також буде ігнорувати значення, які вважаються порожніми, що може бути не бажаною поведінкою. Дивіться Jackson Javadocs для отримання додаткової інформації
davnicwil

Мені подобається ця відповідь, тому що повернення Факультативу з речей, які насправді є необов'язковими, є хорошою ідеєю, і за допомогою лише NON_NULL ви отримаєте щось на зразок { }null, що безглуздо передає ідіому Java споживачеві. те ж саме з AtomicReference - споживачеві все одно, як розробник вирішив забезпечити безпеку потоку під час внутрішнього представлення відповіді.
Лукас Росс

8
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonInclude(JsonInclude.Include.NON_EMPTY)

повинні працювати.

Include.NON_EMPTYвказує, що властивість серіалізується, якщо його значення не є нульовим і не порожнім. Include.NON_NULLвказує, що властивість серіалізується, якщо його значення не є нульовим.


2
JsonInclude.Include.NON_EMPTY- достатньо, оскільки він охоплює справу NOT_NULL
Ілля Бузюк

5

Якщо ви хочете додати це правило до всіх моделей у Jackson 2.6+, використовуйте:

mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

5

Якщо у Spring Boot , ви можете налаштувати Джексона ObjectMapperбезпосередньо за допомогою файлів властивостей.

Приклад application.yml:

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

Можливі значення:

always|non_null|non_absent|non_default|non_empty

Детальніше: https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper


5

Це працюватиме у Spring boot 2.0.3+ та Jackson 2.0+

import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiDTO
{
    // your class variable and 
    // methods
}

1
Це те саме @JsonInclude(JsonInclude.Include.NON_NULL)для мене працювало на весняному завантаженні 2.1.2 та анотаціях Джексона 2.9.0
manasouza

@manasouza Так, вони підтримували послідовність усіх оновлень.
Дева

3

Для Джексона 2,5 використовуйте:

@JsonInclude(content=Include.NON_NULL)

2

Це мене тривалий час турбує, і я нарешті знайшов проблему. Проблема сталася через неправильний імпорт. Раніше я використовував

com.fasterxml.jackson.databind.annotation.JsonSerialize

Який був застарілим. Просто замініть імпорт на

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

і використовувати його як

@JsonSerialize(include=Inclusion.NON_NULL)

2

Глобальна конфігурація, якщо ви використовуєте 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;
    }

}

Встановлення serializationInclusion не додає одне до іншого. public Jackson2ObjectMapperBuilder serializationInclusion(JsonInclude.Include serializationInclusion) { this.serializationInclusion = serializationInclusion; return this; }; Слід використовувати більший радіус перерахунку включення. наприклад, NON_ABSENT включає NON_NULL, а NON_EMPTY включає обидва. Таким чином, це повинен бути лише builder.serializationInclusion(JsonInclude.Include.NON_EMPTY); JacksonInclude doc
Olgun Kaya

2

Якщо ви намагаєтеся серіалізувати список об’єктів, і один з них є недійсним, ви в кінцевому підсумку включаєте нульовий елемент у JSON навіть із

mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

це призведе до:

[{myObject},null]

щоб отримати це:

[{myObject}]

можна зробити щось на кшталт:

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

ПОРАДА: Якщо ви використовуєте DropWizard, ви можете отримати те, ObjectMapperщо використовував Джерсі за допомогоюenvironment.getObjectMapper()


1

У нас є багато відповідей на це питання. Ця відповідь може бути корисною в деяких сценаріях Якщо ви хочете ігнорувати нульові значення, ви можете використовувати NOT_NULL на рівні класу. як зазначено нижче

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

Деколи вам може знадобитися ігнорувати порожні значення, такі як, можливо, ви ініціалізували arrayList, але в цьому списку немає елементів. За цей час за допомогою анотації NOT_EMPTY ігноруйте ці порожні поля значень

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

0

Джексон 2.х + використання

mapper.getSerializationConfig().withSerializationInclusion(JsonInclude.Include.NON_NULL);

.withSerializationInclusion(JsonInclude.Include.NON_NULL)натомість правильно?
herau

Дякую за те, що вказав на це, я
втримаюсь

@ruslan: Мабуть тому, що в документації getSerializationConfig()написано: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

Крім того, ви повинні змінити свій підхід, коли використовуєте Map myVariable, як описано в документації, для усунення нулів:

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

0

Справа перша

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

Справа друга

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

Якщо someStringце недійсне значення, воно буде ігноровано в обох випадках. Якщо someStringє "", це просто ігнорується лише у другому випадку.

Те саме для List = nullабоList.size() = 0

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.