Json.net kullanarak null olursa sınıftaki bir özelliği yoksayma


529

JSON için bir sınıf serileştirmek için Json.NET kullanıyorum .

Ben böyle bir sınıf var:

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

Ben eklemek istiyorum JsonIgnore()için özniteliği Test2Listyalnızca mülkiyet Test2Listolduğunu null. Boş değilse o zaman benim json eklemek istiyorum.

Yanıtlar:


685

James Newton King'e göre: JavaScriptConvert kullanmak yerine serileştiriciyi kendiniz oluşturursanız, yoksaymayı ayarlayabileceğiniz bir NullValueHandlingözellik vardır.

İşte bir örnek:

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

Alternatif olarak, @ amit tarafından önerildiği gibi

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

159
Bu çalışır: JsonConvert.SerializeObject (myObject, Newtonsoft.Json.Formatting.None, yeni JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
Amit

benim için çalıştı ama kullanmak zorunda JsonSerializerSettingsdeğil JsonSerializero sonuncusu için bir hata gösteriyordu
Yazan

1
önemli bir şey - sadece somut sınıflarla (Kişi, Hesap, vb.) çalışır. bunu Sözlük ile denediğimde işe yaramadı
chester89

1
@ Chester89 ile aynı problemim var. ExpandoObject ile null değerler göz ardı edilmez. Bu bir hata gibi görünüyor (json.net 9.0.1 kullanarak)
kwrl

2
Cevap yazıldığında JSON.Net dinamik nesneleri bile desteklemedi. :) Şu anda, teklifinizi yapmak için özel bir dönüştürücü kullanabilirsiniz.
Mrchief

922

Şu JsonPropertyözelliği kullanan alternatif bir çözüm :

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

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

Bu çevrimiçi dokümanda görüldüğü gibi .


19
Kabul edilen cevap daha iyidir çünkü sınıflarınızı Json.net özellikleriyle kirletmez.
Sergey

117
@Sergey kullanım durumunuza bağlıdır. Sadece belirli özellikler için (soruda belirtildiği gibi) olmasını istiyorsanız, bu doğru cevaptır. Genel bir yanıt istiyorsanız, özelliği JsonSerializer'da ayarlamanız gerekir.
sibbl

Kabul edildi - bu basit ve zarif. Oylamaya değer. Harika çalışıyor - VB'de hiçbir şey için serileştirmek istediğiniz nesnede bir özellik ayarlayın ve artık JSON'un bir parçası değildir. Bu sadece Dizeleri ile çalışacaktır. Numaralandırma veya tamsayı olan özellikler her zaman görünecektir - Hiçbir şey ayarlandığında, varsayılan olarak "0" değeri ile sonuçlanmaz.
Destek

3
@Destek referans türü alanlarını boş bırakmanız gerekir, daha sonra özellik veya ayar kullanılarak serileştirilmezler.
Tony

1
Sınıflarınızı birçok özelliğe 'kirletmekten' kaçınmak için işleme kuralını da atayabilirsiniz [JsonObject], ancak özellik adının farklı olduğunu unutmayın. [cevap düzenlendi]
Simon_Weaver

60

@ Sirthomas'ın cevabına benzer şekilde, JSON.NET de şu EmitDefaultValueözelliklere sahiptir DataMemberAttribute:

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

Model türünü zaten kullanıyorsanız [DataContract]ve [DataMember]JSON.NET'e özgü öznitelikler eklemek istemiyorsanız bu istenebilir.


1
Bu çok yardımcı oldu! Özel bir İstisna sınıfı tasarlıyordum ve orada Json.net şeyler eklemek istemiyordum. Teşekkürler!
jpgrassi

2
Bu .Net Core'da çalışmıyordu. @Sirthomas yanıtını önerin: [JsonProperty (NullValueHandling = NullValueHandling.Ignore)] kullanın
Derrick

1
Newtonsoft.Json 10.0.2 ile .Net Core'da benim için iyi çalışıyor.
Karl-Johan Sjögren

33

Yazabilirsin: [JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]

Ayrıca, özellikleri varsayılan değerlerle serileştirmemekle de ilgilenir (yalnızca null değil). Örneğin numaralandırmalar için yararlı olabilir.


3
Bu sirthomas'ın cevabı ile tamamen aynı, neden eklediniz?
OMGtechy

4
Nazik bilgileriniz için, DefaultValueHandling ve NullValueHandling ... arasında fark var
Patel

4
O zaman cevabınızla açıklayabilir misiniz? İlk bakışta, aynı görünüyor ve şimdi, bunun diğer cevaptan nasıl farklı olduğunu / onu nasıl iltifat ettiğini belirtmediniz.
OMGtechy

1
Kabul edilen cevap bazı durumlarda yararlı olabilir, ancak her zaman kullanmak mümkün değildir. Bu sadece doktorun emrettiği şey.
Melbourne Geliştirici

1
Sanırım istediğim bu. Hepsi değil, belirli özellikler üzerinde özel kullanım.
ayaz

23

Serileştirdiğiniz bir nesnedeki tüm null'ları yok saymak için bunu yapabilirsiniz; bu durumda null özellikler JSON'da görünmez

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

12

Kendi sitelerinde bu bağlantıda görüldüğü gibi (http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx) I varsayılan değerleri belirlemek için [Varsayılan ()] kullanarak destek

Bağlantıdan alındı

   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

Net Core'da bu artık çok daha kolay. Startup.cs dosyasında json seçeneklerini eklemeniz yeterlidir ve ayarları oradan yapılandırabilirsiniz.


public void ConfigureServices(IServiceCollection services)

....

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

1

Json.NET ile

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

Sonuç:

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

1

İle System.Text.JsonÇekirdek 3.0 ve .NET bu benim için çalıştı:

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

0

GlennG'nin çok yararlı cevabına (C # 'dan VB.Net'e çevirmek her zaman "açık" değildir) null değerlerin nasıl ele alınacağını yönetmek için bireysel sınıf özelliklerini de dekore edebilirsiniz. Bunu yaparsanız, GlennG'nin önerisindeki küresel JsonSerializerSettings'i kullanmayın, aksi takdirde bireysel süslemeleri geçersiz kılar. Tüketicinin özel bir işlem yapmasına gerek kalmaması için JSON'da boş bir öğenin görünmesini istiyorsanız bu kullanışlı olur. Örneğin, tüketicinin bir dizi isteğe bağlı öğeyi bilmesi gerekiyorsa, ancak şu anda boşsa ... Özellik bildirimindeki dekorasyon şöyle görünür:

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

JSON değişikliğinde hiç görünmesini istemediğiniz özellikler için : = NullValueHandling.Include to : = NullValueHandling.Ignore . Bu arada - XML ​​ve JSON serileştirme için bir özelliği sadece iyi bir şekilde dekore edebileceğinizi buldum (sadece onları yan yana koyun). Bu bana dotnet'te XML serileştiricisini ya da istediği zaman NewtonSoft serileştiricisini arama seçeneği sunuyor - hem yan yana hem de müşterilerim XML veya JSON ile çalışma seçeneğine sahip. Her ikisi de gerektiren müşteriler var çünkü bu bir kapı tokmağı üzerinde sümük gibi kaygan!


0

İşte benzer, ancak başka bir seçenek sunan bir seçenek:

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

Sonra, ben böyle kullanın:

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

Buradaki fark şudur:

  • JsonSerializerSettingsKullanıldığı her yeri başlatır ve yapılandırarak tekrarlanan kodu azaltır .
  • Serileştirilecek her nesnenin her özelliğinin yapılandırılmasında zaman kazandırır.
  • Özelliğin yeniden kullanılabilir bir nesnede açıkça belirtilmesi yerine diğer geliştiricilere serileştirme seçeneklerinde esneklik sağlar.
  • Benim durumum, kodun bir üçüncü taraf kütüphanesi olması ve sınıflarımı yeniden kullanmak isteyen geliştiriciler üzerinde serileştirme seçeneklerini zorlamak istemiyorum.
  • Olası dezavantajlar, diğer geliştiricilerin bilmesi gereken başka bir nesne veya uygulamanızın küçük olup olmadığı ve bu yaklaşımın tek bir serileştirme için önemli olmamasıdır.

-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 diğer yanıtlarda önerilmektedir. Açık değil, cevabınızdaki
yenilikler
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.