So ignorieren Sie eine Eigenschaft in der Klasse, wenn null, mit json.net

529

Ich verwende Json.NET, um eine Klasse in JSON zu serialisieren.

Ich habe die Klasse so:

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

Ich möchte JsonIgnore()der Test2ListEigenschaft nur dann ein Attribut hinzufügen , wenn dies der Fall Test2Listist null. Wenn es nicht null ist, möchte ich es in meinen json aufnehmen.

Amit
quelle

Antworten:

685

Gemäß James Newton King: Wenn Sie den Serializer selbst erstellen, anstatt JavaScriptConvert zu verwenden, gibt es eine NullValueHandlingEigenschaft, die Sie ignorieren können.

Hier ist ein Beispiel:

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

Alternativ, wie von @amit vorgeschlagen

JsonConvert.SerializeObject(myObject, 
                            Newtonsoft.Json.Formatting.None, 
                            new JsonSerializerSettings { 
                                NullValueHandling = NullValueHandling.Ignore
                            });
Mrchief
quelle
159
Dies funktioniert: JsonConvert.SerializeObject (myObject, Newtonsoft.Json.Formatting.None, new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
Amit
es hat bei mir funktioniert, aber ich musste es JsonSerializerSettingsnicht verwenden, JsonSerializerda es einen Fehler für den letzten zeigte
Yazan
1
Eine wichtige Sache - es funktioniert nur mit den konkreten Klassen (Person, Konto usw.). Als ich dies mit Dictionary versuchte, funktionierte es nicht
Chester89
1
Ich habe das gleiche Problem wie @ chester89. Bei einem ExpandoObject werden Nullwerte nicht ignoriert. Das scheint ein Fehler zu sein (mit json.net 9.0.1)
kwrl
2
Als die Antwort geschrieben wurde, unterstützte JSON.Net nicht einmal dynamische Objekte. :) Im Moment können Sie einen benutzerdefinierten Konverter verwenden, um Ihre Gebote abzugeben.
Mrchief
922

Eine alternative Lösung mit dem JsonPropertyAttribut:

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

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

Wie in diesem Online-Dokument zu sehen .

Sirthome
quelle
19
Die akzeptierte Antwort ist besser, da sie Ihre Klassen nicht mit Json.net-Attributen verschmutzt.
Sergey
117
@ Sergey es hängt von Ihrem Anwendungsfall ab. Wenn Sie es nur für bestimmte Eigenschaften haben möchten (wie in der Frage erwähnt), ist dies die richtige Antwort. Wenn Sie eine globale Antwort wünschen, sollten Sie die Eigenschaft im JsonSerializer festlegen.
Geschwister
Einverstanden - das ist einfach und elegant. Es lohnt sich zu stimmen. Funktioniert hervorragend - setzen Sie einfach eine Eigenschaft in dem Objekt, das Sie serialisieren möchten, auf Nothing in VB und es ist nicht mehr Teil des JSON. Dies funktioniert jedoch nur mit Strings. Eigenschaften, die Aufzählungen oder Ganzzahlen sind, werden immer angezeigt. Wenn Sie auf "Nichts" setzen, wird unabhängig davon der Standardwert "0" angezeigt.
Destek
3
@Destek Sie müssen Referenztypfelder auf Null setzen, dann werden sie nicht mithilfe von Attributen oder Einstellungen serialisiert.
Tony
1
Um zu vermeiden, dass Ihre Klassen mit vielen Attributen verschmutzt werden, können Sie auch die Behandlungsregel zuweisen. [JsonObject]Beachten Sie jedoch, dass der Attributname unterschiedlich ist. [bearbeitete Antwort]
Simon_Weaver
60

Ähnlich wie bei der Antwort von @ sirthomas respektiert JSON.NET auch die EmitDefaultValueEigenschaft auf DataMemberAttribute:

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

Dies kann wünschenswert sein, wenn Sie bereits [DataContract]und [DataMember]in Ihrem Modelltyp verwenden und keine JSON.NET-spezifischen Attribute hinzufügen möchten.

Tobias J.
quelle
1
Das ist so hilfreich! Ich habe eine benutzerdefinierte Ausnahmeklasse entworfen und wollte dort keine Json.net-Inhalte hinzufügen. Vielen Dank!
jpgrassi
2
Dies funktionierte in .Net Core nicht. Empfehlen Sie @sirthomas Antwort: Verwenden Sie [JsonProperty (NullValueHandling = NullValueHandling.Ignore)]
Derrick
1
Es funktioniert gut für mich in .Net Core mit Newtonsoft.Json 10.0.2.
Karl-Johan Sjögren
33

Du kannst schreiben: [JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]

Es wird auch dafür gesorgt, dass Eigenschaften nicht mit Standardwerten (nicht nur null) serialisiert werden. Dies kann beispielsweise für Aufzählungen nützlich sein.

Vatsal Patel
quelle
3
Dies ist genau das gleiche wie die Antwort von Sirthomas. Warum haben Sie sie hinzugefügt?
OMGtechy
4
Zu Ihrer Information gibt es einen Unterschied zwischen DefaultValueHandling und NullValueHandling ...
Vatsal Patel
4
Könnten Sie es dann in Ihrer Antwort erklären? Auf den ersten Blick sieht es gleich aus, und jetzt, wo Sie das erwähnt haben, heißt es nicht, wie sich dies von der anderen Antwort unterscheidet / wie es sie ergänzt.
OMGtechy
1
Obwohl die akzeptierte Antwort unter bestimmten Umständen nützlich sein kann, ist es nicht immer möglich, sie zu verwenden. Dies ist genau das, was der Arzt bestellt hat.
Melbourne Entwickler
1
Ich denke das ist was ich wollte. Spezifische Behandlung bestimmter Eigenschaften, nicht aller.
frostymarvelous
23

Sie können dies tun, um alle Nullen in einem Objekt, das Sie serialisieren, zu ignorieren. Alle Null-Eigenschaften werden dann nicht im JSON angezeigt

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

Wie in diesem Link auf ihrer Website zu sehen ist (http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx) I. Unterstützung mit [Default ()] zur Angabe von Standardwerten

Entnommen aus dem 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
// }
Mickey Perlstein
quelle
3

In .Net Core ist dies jetzt viel einfacher. Fügen Sie in Ihrer startup.cs einfach json-Optionen hinzu und Sie können die Einstellungen dort konfigurieren.


public void ConfigureServices(IServiceCollection services)

....

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

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

Das Ergebnis wird sein:

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

Mit System.Text.Jsonund .NET Core 3.0 hat das bei mir funktioniert:

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

Um die sehr hilfreiche Antwort von GlennG ein wenig zu erläutern (die Übersetzung der Syntax von C # in VB.Net ist nicht immer "offensichtlich"), können Sie auch einzelne Klasseneigenschaften dekorieren, um zu verwalten, wie Nullwerte behandelt werden. Wenn Sie dies tun, verwenden Sie nicht die globalen JsonSerializerSettings aus GlennGs Vorschlag, da sonst die einzelnen Dekorationen überschrieben werden. Dies ist praktisch, wenn ein Nullelement im JSON angezeigt werden soll, damit der Verbraucher keine spezielle Behandlung durchführen muss. Wenn der Verbraucher beispielsweise wissen muss, dass normalerweise eine Reihe optionaler Elemente verfügbar ist, diese jedoch derzeit leer sind ... Die Dekoration in der Eigenschaftsdeklaration sieht folgendermaßen aus:

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

Für diese Eigenschaften, die in der JSON-Änderung überhaupt nicht angezeigt werden sollen: = NullValueHandling.Include to : = NullValueHandling.Ignore . Übrigens - ich habe festgestellt, dass Sie eine Eigenschaft sowohl für die XML- als auch für die JSON-Serialisierung problemlos dekorieren können (stellen Sie sie einfach direkt nebeneinander). Dies gibt mir die Möglichkeit, den XML-Serializer in Dotnet oder den NewtonSoft-Serializer nach Belieben aufzurufen - beide arbeiten nebeneinander und meine Kunden haben die Möglichkeit, mit XML oder JSON zu arbeiten. Dies ist wie ein Rotz auf einem Türknauf, da ich Kunden habe, die beides benötigen!

Destek
quelle
0

Hier ist eine Option, die ähnlich ist, aber eine andere Auswahl bietet:

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

Dann benutze ich es so:

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

Der Unterschied hier ist, dass:

  • Reduziert wiederholten Code durch Instanziieren und Konfigurieren JsonSerializerSettingsjedes verwendeten Ortes.
  • Spart Zeit bei der Konfiguration aller Eigenschaften jedes zu serialisierenden Objekts.
  • Bietet anderen Entwicklern weiterhin Flexibilität bei den Serialisierungsoptionen, anstatt die Eigenschaft explizit für ein wiederverwendbares Objekt angeben zu lassen.
  • Mein Anwendungsfall ist, dass der Code eine Bibliothek eines Drittanbieters ist und ich Entwicklern, die meine Klassen wiederverwenden möchten, keine Serialisierungsoptionen aufzwingen möchte.
  • Mögliche Nachteile sind, dass es sich um ein weiteres Objekt handelt, über das andere Entwickler Bescheid wissen müssten, oder ob Ihre Anwendung klein ist und dieser Ansatz für eine einzelne Serialisierung keine Rolle spielt.
Joe Mayo
quelle
-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);
Suresh Bhandari
quelle
settings.NullValueHandling = NullValueHandling.Ignore wird in anderen Antworten empfohlen. Nicht klar, was ist neu in Ihrer Antwort
Michael Freidgeim