Как сказать Джексону игнорировать поле во время сериализации, если его значение равно нулю?

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в геттере, чтобы атрибут отображался, если значение не равно нулю.

Более полный пример доступен в моем ответ на Как предотвратить значения нулевых внутри карты и поля пустых внутри боба от получения сериализовать через Джексон .

Программист Брюс
источник
81
для моего проекта это сработало @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL):; почему-то ваша аннотация была недоступна.
Эммануэль Тузери
13
API немного изменился с выпуском 2.0.
Программист Брюс
11
@ProgrammerBruce -1 измените свой ответ соответственно, так как вы знаете об изменении.
Мартин Асенов
19
Да, я только что подтвердил, что @JsonIncludeнотация не работает, но это работает как шарм: @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) (я использую Jackson 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
В настоящее время (Jackson 2.x) этот подход устарел.
rustyx
39
@JsonInclude (JsonInclude.Include.NON_NULL)
ZiglioUK
3
@JsonSerialize(using = FooSerializer.class, include = JsonSerialize.Inclusion.NON_NULL)не работает Обнуляемые значения сериализуются.
herau
1
Это устарело, но если вам нужно сохранить старые вещи, этот ответ полностью подходит! так что спасибо @WTK :)
DominikAngerer
В качестве дополнительного примечания, Jackson 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 . Для более ранних версий Джексона вам необходимо использовать:

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) 

вместо

@JsonInclude(JsonInclude.Include.NON_NULL)

Если это обновление полезно, пожалуйста, подтвердите ответ ZiglioUK ниже, он указал на более новую аннотацию Jackson 2 задолго до того, как я обновил свой ответ, чтобы использовать его!

davnicwil
источник
не должна ли аннотация на поле ВСЕГДА переопределяться?
Абхинав Вишак
@AbhinavVishak вы правы - спасибо! Это была опечатка, когда я обновил ответ, чтобы использовать Jackson 2. Отредактировано.
Давник будет
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) устарела
Яр
1
@ Да, это не рекомендуется в Jackson 2.x. Я заявил, что вам нужно использовать это только в более ранних версиях Джексона, где не только это не устарело, это единственный вариант.
davnicwil
60

В Jackson 2.x используйте:

@JsonInclude(JsonInclude.Include.NON_NULL)
ZiglioUK
источник
это должно быть размещено на поле.
Ams
1
@ams, эта аннотация должна обернуть класс
Эдгард Лил
Не могли бы вы также включить полное имя? У Джексона есть несколько аннотаций с одним и тем же именем и другим пакетом, так что это неоднозначно.
Винс
Вы говорите, что в Джексоне есть несколько аннотаций @JsonInclude? У меня не было идей. Каким должно быть полное имя? не стесняйтесь редактировать ответ
ZiglioUK
Путаница с именами, скорее всего, связана с тем, что Jackson 1.x и 2.x используют разные пакеты Java для всего, чтобы избежать конфликтов загрузчика классов (с несовместимыми версиями классов). Так как этот ответ для 2.x, пакет для аннотаций будет com.fasterxml.jackson.annotation- у Джексона 1.xorg.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.4 использоватьmapper.setSerializationInclusion(Include.NON_NULL);
Arturo Volpe
12

в моем случае

@JsonInclude(Include.NON_EMPTY)

заставил это работать.

alfthan
источник
2
NON_EMPTY немного отличается от NON_NULL - он будет игнорировать нулевые значения, это правда, но также будет игнорировать значения, которые считаются пустыми, что может не соответствовать желаемому поведению. См. Javadocs Джексона для получения дополнительной информации
davnicwil
Мне нравится этот ответ, потому что возвращение Optional из действительно необязательных вещей - хорошая идея, и только с 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

acdcjunior
источник
5

Это будет работать весной загрузки 2.0.3+ и Джексона 2.0+

import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiDTO
{
    // your class variable and 
    // methods
}
Deva
источник
1
То же самое @JsonInclude(JsonInclude.Include.NON_NULL)сработало для меня в Spring boot 2.1.2 и в аннотациях Jackson 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)
user3443646
источник
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;
    }

}
Xelian
источник
Установка 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
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()

user3474985
источник
1

У нас много ответов на этот вопрос. Этот ответ может быть полезен в некоторых случаях. Если вы хотите игнорировать нулевые значения, вы можете использовать NOT_NULL на уровне класса. как показано ниже

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

Иногда вам может понадобиться игнорировать пустые значения, такие как инициализация arrayList, но в этом списке нет элементов. В это время используется аннотация NOT_EMPTY для игнорирования этих пустых полей значений.

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

источник
0

Джексон 2.x + использовать

mapper.getSerializationConfig().withSerializationInclusion(JsonInclude.Include.NON_NULL);
mekdev
источник
.withSerializationInclusion(JsonInclude.Include.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
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
atom88
источник
0

Первый случай

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

Случай два

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

Если someStringноль, он будет проигнорирован в обоих случаях. Если someStringесть "", то это только будет проигнорировано в случае два.

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

Нгуен Минь Хен
источник