Як ігнорувати властивість у класі, якщо null, використовуючи json.net


529

Я використовую Json.NET для серіалізації класу до JSON.

У мене такий клас:

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

Я хочу додати JsonIgnore()атрибут до Test2Listвластивості лише тоді, коли Test2Listє null. Якщо вона не є нульовою, тоді я хочу включити її до свого json.

Відповіді:


685

Відповідно до Джеймса Ньютона Кінга: Якщо створити серіалізатор самостійно, а не використовувати JavaScriptConvert, є NullValueHandlingвластивість, яку ви можете встановити ігнорувати.

Ось зразок:

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

Як варіант, як пропонує @amit

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

159
Це працює: JsonConvert.SerializeObject (myObject, Newtonsoft.Json.Formatting.None, новий JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
Аміт

він працював на мене, але мені довелося використовувати JsonSerializerSettingsне так, JsonSerializerяк він показав помилку для останнього
Yazan

1
одна важлива річ - вона працює лише з конкретними класами (Особа, Рахунок тощо). коли я спробував це зі словником, не вийшло
chester89

1
У мене така ж проблема, як у @ chester89. З ExpandoObject нульові значення не ігноруються. Здається, це помилка (використовуючи json.net 9.0.1)
kwrl

2
Коли відповідь була написана, JSON.Net навіть не підтримував динамічні об'єкти. :) На даний момент ви можете використовувати спеціальний конвертер, щоб зробити свої ставки.
Mrchief

922

Альтернативне рішення з використанням JsonPropertyатрибута:

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

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

Як видно з цього інтернет-документа .


19
Прийнята відповідь краща, оскільки вона не забруднює ваші заняття атрибутами Json.net.
Сергій

117
@ Сергій, це залежить від вашого випадку використання. Якщо ви хочете мати його лише для конкретних властивостей (як зазначено у питанні), то це правильна відповідь. Якщо ви хочете отримати глобальну відповідь, вам слід встановити властивість у JsonSerializer.
сібл

Домовились - це просто і елегантно. Варто звернути увагу. Працює чудово - просто встановіть властивість у об’єкті, який ви хочете серіалізувати у Nothing у VB, і він більше не є частиною JSON. Це буде працювати лише зі Strings. Властивості, які є перерахунками або цілими числами, завжди відображатимуться - якщо параметр "Ніщо" не приводить до значення за замовчуванням "0" незалежно.
Дестек

3
@Destek вам потрібно зробити поля посилань типу нульовими, тоді вони не будуть серіалізовані за допомогою атрибута чи налаштування.
Тоні

1
Щоб уникнути "забруднення" ваших класів багатьма атрибутами, ви також можете призначити правило обробки [JsonObject], але зауважте, що назва атрибута інша. [відредагована відповідь]
Simon_Weaver

60

Подібний відповідь @ sirthomas'S, JSON.NET також поважає в EmitDefaultValueвласність на DataMemberAttribute:

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

Це може бути бажано, якщо ви вже використовуєте [DataContract]та [DataMember]у своєму типі моделі та не хочете додавати атрибути, характерні для JSON.NET.


1
Це так корисно! Я розробляв спеціальний клас винятку, і я не хотів туди додавати речі Json.net. Дякую!
jpgrassi

2
Це не працювало в .Net Core. Рекомендуйте @sirthomas відповідь: використовуйте [JsonProperty (NullValueHandling = NullValueHandling.Ignore)]
Derrick,

1
Для мене це чудово працює в .Net Core з Newtonsoft.Json 10.0.2.
Карл-Йохан Шьогрен

33

Ви можете написати: [JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]

Він також дбає про не серіалізацію властивостей зі значеннями за замовчуванням (не тільки null). Це може бути корисно для переліків, наприклад.


3
Це точно так само, як відповідь сиртома, чому ви додали його?
OMGtechy

4
Для вашої доброї інформації є різниця між DefaultValueHandling та NullValueHandling ...
Vatsal Patel

4
Чи можете ви пояснити це тоді у своїй відповіді? На перший погляд це виглядає так само, і тепер ви вже згадали про це, в ньому не зазначено, чим це відрізняється від іншої відповіді / як це компліментує.
OMGtechy

1
Хоча прийнята відповідь може бути корисною в деяких обставинах, її не завжди можливо використовувати. Це саме те, що призначив лікар.
Мельбурнський розробник

1
Я думаю, що саме цього я хотів. Спеціальне поводження з певними властивостями, не всі.
frostymarvelous

23

Ви можете зробити це, щоб ігнорувати всі нулі об’єкта, який ви серіалізуєте, і будь-які нульові властивості не з’являться в JSON

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

12

Як видно з цього посилання на їхньому сайті (http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx) I підтримка за допомогою [Default ()] для визначення значень за замовчуванням

Взято за посиланням

   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 зараз це набагато простіше. У свій startup.cs просто додайте параметри json і ви зможете налаштувати там налаштування.


public void ConfigureServices(IServiceCollection services)

....

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

1

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

Результатом буде:

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

1

З System.Text.Jsonі .NET Core 3.0 це працювало для мене:

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

0

Щоб трохи пояснити дуже корисну відповідь GlennG (переклад синтаксису з C # на VB.Net не завжди є "очевидним"), ви також можете прикрасити властивості окремих класів, щоб керувати тим, як обробляються нульові значення. Якщо ви це зробите, не використовуйте глобальні JsonSerializerSettings з пропозицій GlennG, інакше це перекриє окремі прикраси. Це стане в нагоді, якщо ви хочете, щоб нульовий товар з’явився в JSON, тому споживачеві не доведеться робити якісь спеціальні обробки. Якщо, наприклад, споживачеві потрібно знати, що масив необов’язкових елементів зазвичай доступний, але наразі порожній ... Прикраса в декларації властивості виглядає приблизно так:

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

Для тих властивостей, які ви взагалі не бажаєте відображатись у зміні JSON : = NullValueHandling.Include to : = NullValueHandling.Ignore . До речі - я виявив, що ви можете добре прикрасити властивість і для серіалізації XML, і для JSON (просто покладіть їх прямо поруч). Це дає мені можливість закликати серіалізатор XML в dotnet або серіалізатор NewtonSoft за бажанням - і обидва працюють, і мої клієнти мають можливість працювати з XML або JSON. Це гладко, як соплі на дверній ручці, оскільки у мене є клієнти, які вимагають обох!


0

Ось варіант, подібний, але надає інший вибір:

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

Потім я використовую це так:

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

Різниця тут полягає в тому, що:

  • Зменшує повторний код шляхом інстанції та налаштування JsonSerializerSettings кожного використовуваного місця.
  • Економить час на налаштування кожної властивості кожного об'єкта, що підлягає серіалізації.
  • Все-таки надає іншим розробникам гнучкість у параметрах серіалізації, замість того, щоб властивість було чітко вказано на об'єкт багаторазового використання.
  • Моє використання полягає в тому, що код є бібліотекою сторонніх розробників, і я не хочу форсувати параметри серіалізації для розробників, які хочуть повторно використовувати мої класи.
  • Потенційні недоліки полягають у тому, що це ще один предмет, про який мали би знати інші розробники, або якщо ваша програма мала, і такий підхід не матиме значення для однієї серіалізації.

-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 вказується в інших відповідях. Не зрозуміло, що нового у вашій відповіді
Майкл Фрейджім
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.