web-dev-qa-db-fra.com

Comment ignorer une propriété en classe si null, en utilisant json.net

J'utilise Json.NET pour sérialiser une classe en JSON.

J'ai la classe comme ça:

class Test1
{
    [JsonProperty("id")]
    public string ID { get; set; }
    [JsonProperty("label")]
    public string Label { get; set; }
    [JsonProperty("url")]
    public string URL { get; set; }
    [JsonProperty("item")]
    public List<Test2> Test2List { get; set; }
}

Je souhaite ajouter un attribut JsonIgnore() à la propriété Test2List uniquement lorsque Test2List est null. Si ce n'est pas nul alors je veux l'inclure dans mon json.

468
Amit

Selon James Newton King: Si vous créez le sérialiseur vous-même plutôt que d'utiliser JavaScriptConvert, il existe une propriété NullValueHandling que vous pouvez définir pour l'ignorer.

Voici un exemple:

JsonSerializer _jsonWriter = new JsonSerializer {
                                 NullValueHandling = NullValueHandling.Ignore
                             };

Alternativement, comme suggéré par @amit

JsonConvert.SerializeObject(myObject, 
                            Newtonsoft.Json.Formatting.None, 
                            new JsonSerializerSettings { 
                                NullValueHandling = NullValueHandling.Ignore
                            });
620
Mrchief

Une autre solution utilisant l'attribut JsonProperty:

[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
// or
[JsonProperty("property_name", NullValueHandling=NullValueHandling.Ignore)]

// or for all properties in a class
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]

Comme on le voit dans ce document en ligne .

811
sirthomas

Semblable à la réponse de @ sirthomas, JSON.NET respecte également la propriété EmitDefaultValue sur DataMemberAttribute:

[DataMember(Name="property_name", EmitDefaultValue=false)]

Cela peut être souhaitable si vous utilisez déjà [DataContract] et [DataMember] dans votre type de modèle et ne souhaitez pas ajouter d'attributs spécifiques à JSON.NET.

54
Toby J

Vous pouvez écrire: [JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]

Il prend également soin de ne pas sérialiser les propriétés avec les valeurs par défaut (pas seulement null). Cela peut être utile pour des enums par exemple.

29
Er Vatsal D Patel

Vous pouvez le faire pour ignorer toutes les valeurs NULL dans un objet que vous sérialisez. Aucune propriété NULL n'apparaîtra alors dans le fichier JSON.

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
var myJson = JsonConvert.SerializeObject(myObject, settings);
21
Chris Halcrow

Comme on peut le voir sur ce lien sur leur site (http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx) I supporte l'utilisation de [Default ()] pour spécifier les valeurs par défaut

Tiré du lien

   public class Invoice
{
  public string Company { get; set; }
  public decimal Amount { get; set; }

  // false is default value of bool
  public bool Paid { get; set; }
  // null is default value of nullable
  public DateTime? PaidDate { get; set; }

  // customize default values
  [DefaultValue(30)]
  public int FollowUpDays { get; set; }
  [DefaultValue("")]
  public string FollowUpEmailAddress { get; set; }
}


Invoice invoice = new Invoice
{
  Company = "Acme Ltd.",
  Amount = 50.0m,
  Paid = false,
  FollowUpDays = 30,
  FollowUpEmailAddress = string.Empty,
  PaidDate = null
};

string included = JsonConvert.SerializeObject(invoice,
  Formatting.Indented,
  new JsonSerializerSettings { });

// {
//   "Company": "Acme Ltd.",
//   "Amount": 50.0,
//   "Paid": false,
//   "PaidDate": null,
//   "FollowUpDays": 30,
//   "FollowUpEmailAddress": ""
// }

string ignored = JsonConvert.SerializeObject(invoice,
  Formatting.Indented,
  new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });

// {
//   "Company": "Acme Ltd.",
//   "Amount": 50.0
// }
12

Une adaptation à la réponse de @ Mrchief/@ amit, mais pour les personnes utilisant VB

 Dim JSONOut As String = JsonConvert.SerializeObject(
           myContainerObject, 
           New JsonSerializerSettings With {
                 .NullValueHandling = NullValueHandling.Ignore
               }
  )

Voir: "Initialiseurs d'objet: Types nommés et anonymes (Visual Basic)"

https://msdn.Microsoft.com/en-us/library/bb385125.aspx

4
GlennG

Pour expliquer légèrement la réponse très utile de GlennG (traduire la syntaxe de C # en VB.Net n’est pas toujours "évident"), vous pouvez également décorer des propriétés de classe individuelles pour gérer le traitement des valeurs NULL. Si vous faites cela, n'utilisez pas la suggestion globale de JsonSerializerSettings de GlennG, sinon elle remplacera les décorations individuelles. Cela s'avère pratique si vous souhaitez qu'un élément null apparaisse dans le code JSON afin que le consommateur n'ait pas à effectuer de traitement spécial. Si, par exemple, le consommateur doit savoir qu'un tableau d'éléments facultatifs est normalement disponible, mais qu'il est actuellement vide ... La décoration dans la déclaration de propriété ressemble à ceci:

<JsonPropertyAttribute("MyProperty", DefaultValueHandling:=NullValueHandling.Include)> Public Property MyProperty As New List(of String)

Pour les propriétés que vous ne souhaitez pas voir apparaître dans la modification JSON : = = NullValueHandling.Include à : = NullValueHandling.Ignore. Soit dit en passant, j'ai constaté que vous pouviez très bien décorer une propriété pour la sérialisation XML et JSON (placez-les juste les unes à côté des autres). Cela me donne la possibilité d'appeler le sérialiseur XML dans dotnet ou le sérialiseur NewtonSoft à volonté. Les deux fonctionnent côte à côte et mes clients ont la possibilité de travailler avec XML ou JSON. C'est lisse comme une morue sur une poignée de porte depuis que j'ai des clients qui exigent les deux!

0
Destek

Voici une option similaire, mais offrant un autre choix:

public class DefaultJsonSerializer : JsonSerializerSettings
{
    public DefaultJsonSerializer()
    {
        NullValueHandling = NullValueHandling.Ignore;
    }
}

Ensuite, je l'utilise comme ceci:

JsonConvert.SerializeObject(postObj, new DefaultJsonSerializer());

La différence ici est que:

  • Réduit le code répété en instanciant et en configurant JsonSerializerSettings à chaque endroit où il est utilisé.
  • Gain de temps dans la configuration de chaque propriété de chaque objet à sérialiser.
  • Donne toujours aux autres développeurs une flexibilité dans les options de sérialisation, au lieu d’avoir la propriété explicitement spécifiée sur un objet réutilisable.
  • Mon cas d'utilisation est que le code est une bibliothèque tierce partie et je ne souhaite pas forcer les options de sérialisation aux développeurs qui souhaitent réutiliser mes classes.
  • Les inconvénients potentiels sont que c'est un autre objet que d'autres développeurs devraient connaître, ou si votre application est petite et que cette approche n'aurait pas d'importance pour une seule sérialisation.
0
Joe Mayo

En .Net Core, c'est beaucoup plus facile maintenant. Dans votre startup.cs, ajoutez simplement les options JSON et vous pourrez y configurer les paramètres.


public void ConfigureServices(IServiceCollection services)

....

services.AddMvc().AddJsonOptions(options =>
{
   options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;               
});

0
Hizzy

Avec Json.NET

 public class Movie
 {
            public string Name { get; set; }
            public string Description { get; set; }
            public string Classification { get; set; }
            public string Studio { get; set; }
            public DateTime? ReleaseDate { get; set; }
            public List<string> ReleaseCountries { get; set; }
 }

 Movie movie = new Movie();
 movie.Name = "Bad Boys III";
 movie.Description = "It's no Bad Boys";

 string ignored = JsonConvert.SerializeObject(movie,
            Formatting.Indented,
            new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

Le résultat sera:

{
   "Name": "Bad Boys III",
   "Description": "It's no Bad Boys"
 }
0
Rafy