Comment ignorer une propriété dans la classe si null, en utilisant json.net
J'utilise Json.NET {[7] } pour sérialiser une classe en JSON.
J'ai la classe comme ceci:
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 veux ajouter un JsonIgnore()
attribut Test2List
bien que lorsque Test2List
est null
. Si ce n'est pas null, je veux l'inclure dans mon json.
10 réponses
Selon James Newton King: si vous créez le sérialiseur vous-même plutôt que D'utiliser JavaScriptConvert, il y a un NullValueHandling
propriété que vous pouvez définir pour 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
});
Une solution alternative utilisant l'attribut JsonProperty
:
[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
//or
[JsonProperty("property_name", NullValueHandling=NullValueHandling.Ignore)]
Comme dans ce document en ligne.
Similaire à 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 que vous ne souhaitez pas ajouter D'attributs spécifiques à JSON.NET.
Vous pouvez le faire pour ignorer toutes les valeurs NULL dans un objet que vous sérialisez, et les propriétés null n'apparaîtront pas dans le JSON
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
var myJson = JsonConvert.SerializeObject(myObject, settings);
, Vous pouvez écrire: [JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]
Il prend également soin de ne pas sérialiser les propriétés avec des valeurs par défaut (pas seulement null). Cela peut être utile pour les énumérations par exemple.
Comme on peut le voir dans ce lien sur leur site (http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx) je 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
// }
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'objets: types nommés et anonymes (Visual Basic)"
Pour exposer légèrement la réponse très utile de GlennG (traduire la syntaxe de C # à VB.Net n'est pas toujours "évident") vous pouvez également décorer les propriétés de classe individuelles pour gérer la façon dont les valeurs null sont traitées. Si vous faites cela, n'utilisez pas le JsonSerializerSettings global de la suggestion de GlennG, sinon il remplacera les décorations individuelles. Cela est pratique si vous voulez qu'un élément null apparaisse dans le JSON afin que le consommateur n'ait pas à faire de manipulation spéciale. Si, par exemple, le consommateur doit savoir qu'un tableau d'éléments optionnels 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 ces propriétés que vous ne voulez pas voir apparaître du tout dans le changement JSON :=NullValueHandling.Inclure à :=NullValueHandling.Ignorer . En passant-j'ai trouvé que vous pouvez décorer une propriété pour la sérialisation XML et JSON très bien (il suffit de les mettre juste à côté de l'autre). Cela me donne de l' l'option 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. Ceci est lisse comme morve sur une poignée de porte depuis que j " ai des clients qui ont besoin à la fois!
Voici une option qui est similaire, mais qui offre 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 utilisé. - permet de gagner du 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, plutôt que d'avoir la propriété explicitement spécifiée sur un réutilisable objet.
- mon cas d'utilisation est que le code est une bibliothèque tierce et je ne veux pas forcer les options de sérialisation sur les développeurs qui voudraient réutiliser mes classes.
- les inconvénients potentiels sont que c'est un autre objet que les autres développeurs auraient besoin de connaître, ou si votre application est petite et que cette approche n'aurait pas d'importance pour une seule sérialisation.
var settings = new JsonSerializerSettings();
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
settings.NullValueHandling = NullValueHandling.Ignore;
//you can add multiple settings and then use it
var bodyAsJson = JsonConvert.SerializeObject(body, Formatting.Indented, settings);