Comment dire à Jackson d'ignorer un champ lors de la sérialisation si sa valeur est nulle?

687

Comment Jackson peut-il être configuré pour ignorer une valeur de champ pendant la sérialisation si la valeur de ce champ est nulle.

Par exemple:

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; 
}
ams
la source

Réponses:

1102

Pour supprimer les propriétés de sérialisation avec des valeurs nulles à l'aide de Jackson> 2.0, vous pouvez configurer ObjectMapperdirectement ou utiliser l' @JsonIncludeannotation:

mapper.setSerializationInclusion(Include.NON_NULL);

ou:

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

Alternativement, vous pouvez utiliser @JsonIncludedans un getter afin que l'attribut soit affiché si la valeur n'est pas nulle.

Un exemple plus complet est disponible dans ma réponse à Comment empêcher les valeurs nulles à l'intérieur d'une carte et les champs null à l'intérieur d'un bean d'être sérialisés via Jackson .

Programmeur Bruce
la source
81
pour mon projet, cela a fonctionné @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL):; d'une certaine manière, votre annotation n'était pas disponible.
Emmanuel Touzery
13
L'API a un peu changé avec la version 2.0.
Programmeur Bruce
10
@ProgrammerBruce -1 changez votre réponse en conséquence puisque vous êtes au courant du changement.
Martin Asenov
19
Oui, je viens de confirmer que la @JsonIncludenotation ne fonctionne pas, mais cela fonctionne comme un charme: @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) (j'utilise Jackson 1.9.12 avec Spring 3.2.2.)
gstroup
17
@MartinAsenov - la réponse montre l'API la plus récente; il a été changé de la @JsonSerializesyntaxe à @JsonInclude. L'ancienne syntaxe est obsolète.
Ramassage Logan
128

Avec Jackson> 1.9.11 et <2.x, utilisez l' @JsonSerializeannotation pour ce faire:

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)

WTK
la source
10
De nos jours (Jackson 2.x), cette approche est obsolète.
rustyx
39
@JsonInclude (JsonInclude.Include.NON_NULL)
ZiglioUK
3
@JsonSerialize(using = FooSerializer.class, include = JsonSerialize.Inclusion.NON_NULL)ne fonctionne pas. les valeurs nullables sont sérialisées.
herau
1
C'est obsolète mais si vous avez besoin de conserver d'anciennes choses, cette réponse est tout à fait correcte! alors merci @WTK :)
DominikAngerer
En guise de remarque, Jackson 1.9.12 est standard dans WebSphere 8.5, j'espère que cette information fera gagner beaucoup de temps à quelqu'un d'autre, il m'a fallu le comprendre :-)
bakoyaro
122

Juste pour développer les autres réponses - si vous devez contrôler l'omission des valeurs nulles sur une base par champ, annotez le champ en question (ou annotez alternativement le 'getter' du champ).

exemple - ici seulement fieldOnesera omis de json s'il est nul. fieldTwosera toujours inclus, qu'il soit nul ou non.

public class Foo {

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

    private String fieldTwo;
}

Pour omettre toutes les valeurs nulles de la classe par défaut, annotez la classe. Les annotations par champ / getter peuvent toujours être utilisées pour remplacer cette valeur par défaut si nécessaire.

exemple - ici fieldOneet fieldTwoseront supprimés de json s'ils sont respectivement nuls, car il s'agit de la valeur par défaut définie par l'annotation de classe. fieldThreecependant, remplacera la valeur par défaut et sera toujours inclus, en raison de l'annotation sur le champ.

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

    private String fieldOne;

    private String fieldTwo;

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

MISE À JOUR

Ce qui précède est pour Jackson 2 . Pour les versions antérieures de Jackson, vous devez utiliser:

@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) 

au lieu de

@JsonInclude(JsonInclude.Include.NON_NULL)

Si cette mise à jour est utile, veuillez noter la réponse de ZiglioUK ci-dessous, elle a souligné la nouvelle annotation Jackson 2 bien avant de mettre à jour ma réponse pour l'utiliser!

davnicwil
la source
l'annotation sur le champ ne doit-elle pas toujours être remplacée?
Abhinav Vishak
@AbhinavVishak vous avez raison - merci! C'était une faute de frappe lorsque j'ai mis à jour la réponse pour utiliser Jackson 2. Modifié.
davnicwil
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) est déconseillé
Yar
1
@ Oui, c'est obsolète dans Jackson 2.x. J'ai déclaré que vous devez utiliser cela uniquement dans les versions antérieures de Jackson où non seulement il n'est pas obsolète, c'est la seule option.
davnicwil
60

Dans Jackson 2.x, utilisez:

@JsonInclude(JsonInclude.Include.NON_NULL)
ZiglioUK
la source
est-ce à placer sur le terrain.
Ams
1
@ams, cette annotation devrait encapsuler une classe
Edgard Leal
Pourriez-vous également inclure le nom complet? Jackson a plusieurs annotations avec le même nom et un package différent, ce qui est ambigu.
Vince
dites-vous qu'il y a plusieurs annotations @JsonInclude dans Jackson? Je n'en avais aucune idée. Quel devrait être alors le nom complet? n'hésitez pas à modifier la réponse
ZiglioUK
La confusion avec les noms est probablement due au fait que Jackson 1.x et 2.x utilisent différents packages Java pour tout, afin d'éviter les conflits de chargeur de classe (par rapport aux versions de classe incompatibles). Comme cette réponse est pour 2.x, le package d'annotations seraitcom.fasterxml.jackson.annotation - Jackson 1.x avaitorg.codehaus.jackson.annoation
StaxMan
39

Vous pouvez utiliser la configuration de mappeur suivante:

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

Depuis 2.5, vous pouvez utiliser:

mapper.setSerializationInclusion(Include.NON_NULL);
Eren Yilmaz
la source
3
Étant donné que cela est obsolète en 1.9, utilisez mapper.getSerializationConfig (). WithSerializationInclusion (JsonSerialize.Inclusion.NON_NULL);
Asa
7
..ou directement: mapper.setSerializationInclusion (NON_NULL);
Asa
@ruslan: Probablement parce que la documentation de getSerializationConfig() dit: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
Pour la version 2.5.4mapper.setSerializationInclusion(Include.NON_NULL);
Arturo Volpe du
12

dans mon cas

@JsonInclude(Include.NON_EMPTY)

l'a fait fonctionner.

alfthan
la source
2
NON_EMPTY est subtilement différent de NON_NULL - il ignorera les valeurs nulles, c'est vrai, mais ignorera également les valeurs considérées comme vides, ce qui peut ne pas être le comportement souhaité. Voir les javadocs Jackson pour plus d'informations
davnicwil
j'aime cette réponse parce que retourner Facultatif à partir de choses qui sont vraiment facultatives est une bonne idée, et avec juste NON_NULL vous obtiendriez quelque chose comme { }pour null, qui transfère inutilement un idiome Java au consommateur. Même chose avec AtomicReference - le consommateur ne se soucie pas de la façon dont le développeur a choisi d'appliquer la sécurité des threads sur la représentation interne de la réponse.
Lucas Ross
8
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonInclude(JsonInclude.Include.NON_EMPTY)

devrait marcher.

Include.NON_EMPTYindique que la propriété est sérialisée si sa valeur n'est pas nulle et non vide. Include.NON_NULLindique que la propriété est sérialisée si sa valeur n'est pas nulle.

Neha Gangwar
la source
2
JsonInclude.Include.NON_EMPTY- est suffisant car il couvre le cas NOT_NULL
Ilya Buziuk
5

Si vous souhaitez ajouter cette règle à tous les modèles de Jackson 2.6+, utilisez:

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

Si dans Spring Boot , vous pouvez personnaliser le jackson ObjectMapperdirectement via les fichiers de propriétés.

Exemple application.yml:

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

Les valeurs possibles sont:

always|non_null|non_absent|non_default|non_empty

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

acdcjunior
la source
5

Cela fonctionnera dans Spring boot 2.0.3+ et Jackson 2.0+

import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiDTO
{
    // your class variable and 
    // methods
}
Deva
la source
1
Cela a @JsonInclude(JsonInclude.Include.NON_NULL)fonctionné pour moi sur Spring boot 2.1.2 et Jackson annotations 2.9.0
manasouza
@manasouza Oui, ils ont maintenu la cohérence de toutes les mises à jour.
Deva
3

Pour Jackson 2.5, utilisez:

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

Cela me préoccupe depuis un certain temps et j'ai finalement trouvé le problème. Le problème était dû à une mauvaise importation. Plus tôt, j'utilisais

com.fasterxml.jackson.databind.annotation.JsonSerialize

Qui avait été déprécié. Remplacez simplement l'importation par

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

et l'utiliser comme

@JsonSerialize(include=Inclusion.NON_NULL)
user3443646
la source
2

Configuration globale si vous utilisez 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
la source
La définition de l'inclusion serialization n'ajoute pas l'un sur l'autre. public Jackson2ObjectMapperBuilder serializationInclusion(JsonInclude.Include serializationInclusion) { this.serializationInclusion = serializationInclusion; return this; }; Il faut utiliser le plus grand rayon d'énumération d'inclusion. par exemple NON_ABSENT inclut NON_NULL et NON_EMPTY inclut les deux. Ainsi, il ne devrait être que builder.serializationInclusion(JsonInclude.Include.NON_EMPTY); JacksonInclude doc
Olgun Kaya
2

Si vous essayez de sérialiser une liste d'objets et que l'un d'eux est nul, vous finirez par inclure l'élément nul dans le JSON même avec

mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

aura pour résultat:

[{myObject},null]

pour obtenir ceci:

[{myObject}]

on peut faire quelque chose comme:

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

CONSEIL: Si vous utilisez DropWizard, vous pouvez récupérer celui ObjectMapperutilisé par Jersey en utilisantenvironment.getObjectMapper()

user3474985
la source
1

Nous avons beaucoup de réponses à cette question. Cette réponse peut être utile dans certains scénarios. Si vous souhaitez ignorer les valeurs nulles, vous pouvez utiliser NOT_NULL au niveau de la classe. comme ci-dessous

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

Parfois, vous devrez peut-être ignorer les valeurs vides telles que vous avez peut-être initialisé le arrayList, mais il n'y a aucun élément dans cette liste.

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

la source
0

Jackson 2.x + utilisation

mapper.getSerializationConfig().withSerializationInclusion(JsonInclude.Include.NON_NULL);
mekdev
la source
.withSerializationInclusion(JsonInclude.Include.NON_NULL)à la place, non?
herau
Merci de l'avoir signalé, je
m'arrêterai
@ruslan: Probablement parce que la documentation de getSerializationConfig()dit: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

De plus, vous devez changer votre approche lorsque vous utilisez Map myVariable comme décrit dans la documentation pour éliminer les valeurs Null:

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
la source
0

Premier cas

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

Deuxième cas

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

Si someStringest nul, il sera ignoré dans les deux cas. SisomeString est "", il ne sera ignoré que dans le deuxième cas.

La même chose pour List = nullouList.size() = 0

Nguyen Minh Hien
la source