Come ignorare una proprietà in classe se nulla, usando json.net


529

sto usando Json.NET per serializzare una classe su JSON.

Ho la classe in questo modo:

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

Voglio aggiungere un JsonIgnore()attributo alla Test2Listproprietà solo quando lo Test2Listè null. Se non è null, allora voglio includerlo nel mio json.

Risposte:


685

Secondo James Newton King: se crei tu stesso il serializzatore anziché utilizzare JavaScriptConvert, c'è una NullValueHandlingproprietà che puoi impostare per ignorare.

Ecco un esempio:

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

In alternativa, come suggerito da @amit

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

159
Funziona: JsonConvert.SerializeObject (myObject, Newtonsoft.Json.Formatting.None, nuovo JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
Entro il

Ha funzionato per me, ma ho dovuto usare JsonSerializerSettingsnon JsonSerializercome ha mostrato un errore per l'ultimo
Yazan

1
una cosa importante: funziona solo con le classi concrete (Persona, Conto, ecc.). quando l'ho provato con Dizionario, non ha funzionato
chester89,

1
Ho lo stesso problema di @ chester89. Con ExpandoObject i valori null non vengono ignorati. Questo sembra essere un bug (usando json.net 9.0.1)
kwrl il

2
Quando la risposta è stata scritta, JSON.Net non supportava nemmeno gli oggetti dinamici. :) Al momento, puoi utilizzare un convertitore personalizzato per fare le tue offerte.
Mrchief,

923

Una soluzione alternativa che utilizza l' JsonPropertyattributo:

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

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

Come visto in questo documento online .


19
La risposta accettata è migliore perché non inquina le tue classi con gli attributi Json.net.
Sergey

117
@Sergey dipende dal tuo caso d'uso. Se vuoi averlo solo per proprietà specifiche (come menzionato nella domanda), allora questa è la risposta corretta. Se si desidera una risposta globale, è necessario impostare la proprietà in JsonSerializer.
sibbl,

D'accordo - questo è semplice ed elegante. Vale la pena votare. Funziona alla grande: basta impostare una proprietà nell'oggetto che si desidera serializzare su Nothing in VB e non fa più parte di JSON. Funzionerà però solo con le stringhe. Le proprietà che sono enumerazioni o numeri interi verranno sempre visualizzate - impostando su Nothing il valore predefinito è "0", indipendentemente.
Destek,

3
@Destek è necessario rendere nulli i campi dei tipi di riferimenti, quindi non verranno serializzati utilizzando l'attributo o l'impostazione.
Tony,

1
Per evitare di "inquinare" le tue classi con molti attributi, puoi anche assegnare la regola di gestione [JsonObject], ma nota che il nome dell'attributo è diverso. [risposta modificata]
Simon_Weaver il

60

Simile alla risposta di @ sirthomas, JSON.NET rispetta anche la EmitDefaultValueproprietà su DataMemberAttribute:

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

Ciò può essere desiderabile se si sta già utilizzando [DataContract]e [DataMember]nel tipo di modello e non si desidera aggiungere attributi specifici di JSON.NET.


1
Questo è così utile! Stavo progettando una classe di eccezione personalizzata e non volevo aggiungere elementi Json.net lì dentro. Grazie!
jpgrassi,

2
Questo non funzionava in .Net Core. Raccomandare la risposta @sirthomas: utilizzare [JsonProperty (NullValueHandling = NullValueHandling.Ignore)]
Derrick

1
Funziona bene per me in .Net Core con Newtonsoft.Json 10.0.2.
Karl-Johan Sjögren,

33

Tu puoi scrivere: [JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]

Si occupa anche di non serializzare le proprietà con valori predefiniti (non solo nulli). Può essere utile, ad esempio, per le enumerazioni.


3
È esattamente la stessa della risposta di Sirthomas, perché l'hai aggiunta?
OMGtechy,

4
Per vostra gentile informazione, c'è differenza tra DefaultValueHandling e NullValueHandling ...
Vatsal Patel

4
Potresti spiegarlo nella tua risposta allora? A prima vista, sembra lo stesso, e ora hai detto che, non afferma come questo sia diverso dall'altra risposta / come lo complimenti.
OMGtechy,

1
Sebbene la risposta accettata possa essere utile in alcune circostanze, non è sempre possibile utilizzarla. Questo è esattamente ciò che il medico ha ordinato.
Sviluppatore Melbourne,

1
Penso che sia quello che volevo. Gestione specifica di determinate proprietà, non tutte.
frostymarvelous,

23

È possibile farlo per ignorare tutti i null in un oggetto che si sta serializzando e tutte le proprietà null non verranno quindi visualizzate in JSON

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

12

Come si può vedere in questo link sul loro sito (http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx) I supporta l'utilizzo di [Predefinito ()] per specificare i valori predefiniti

Tratto dal link

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


3

In .Net Core ora è molto più semplice. Nel tuo startup.cs basta aggiungere le opzioni json e qui puoi configurare le impostazioni.


public void ConfigureServices(IServiceCollection services)

....

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

1

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

Il risultato sarà:

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

1

Con System.Text.Jsone .NET Core 3.0 questo ha funzionato per me:

var jsonSerializerOptions = new JsonSerializerOptions()
{
    IgnoreNullValues = true
};
var myJson = JsonSerializer.Serialize(myObject, jsonSerializerOptions );

0

Per spiegare leggermente la risposta molto utile di GlennG (tradurre la sintassi da C # a VB.Net non è sempre "ovvia") puoi anche decorare le proprietà delle singole classi per gestire la gestione dei valori null. In questo caso, non utilizzare le impostazioni globali JsonSerializerSettings dal suggerimento di GlennG, altrimenti sostituirà le singole decorazioni. Ciò è utile se si desidera che un elemento null venga visualizzato in JSON in modo che il consumatore non debba eseguire alcuna gestione speciale. Se, ad esempio, il consumatore deve conoscere una serie di articoli opzionali è normalmente disponibile, ma è attualmente vuoto ... La decorazione nella dichiarazione di proprietà è simile alla seguente:

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

Per quelle proprietà che non si desidera visualizzare nella modifica JSON : = NullValueHandling.Include to : = NullValueHandling.Ignore . A proposito, ho scoperto che puoi decorare bene una proprietà per la serializzazione sia XML che JSON (mettili uno accanto all'altro). Questo mi dà la possibilità di chiamare a piacere il serializzatore XML in dotnet o il serializzatore NewtonSoft: entrambi lavorano fianco a fianco e i miei clienti hanno la possibilità di lavorare con XML o JSON. Questo è perfetto come il moccio su una maniglia della porta poiché ho clienti che richiedono entrambi!


0

Ecco un'opzione simile, ma offre un'altra scelta:

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

Quindi, lo uso in questo modo:

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

La differenza qui è che:

  • Riduce il codice ripetuto creando un'istanza e configurando JsonSerializerSettingsogni luogo utilizzato.
  • Risparmia tempo nella configurazione di ogni proprietà di ogni oggetto da serializzare.
  • Offre comunque agli altri sviluppatori flessibilità nelle opzioni di serializzazione, anziché avere la proprietà esplicitamente specificata su un oggetto riutilizzabile.
  • Il mio caso d'uso è che il codice è una libreria di terze parti e non voglio forzare le opzioni di serializzazione su sviluppatori che vorrebbero riutilizzare le mie lezioni.
  • I potenziali svantaggi sono che si tratta di un altro oggetto che altri sviluppatori dovrebbero conoscere o se l'applicazione è di piccole dimensioni e questo approccio non avrebbe importanza per una singola serializzazione.

-1
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);

settings.NullValueHandling = NullValueHandling.Ignore è suggerito in altre risposte. Non è chiaro, cosa c'è di nuovo nella tua risposta
Michael Freidgeim il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.