如何使用json.net忽略类中的属性(如果为null)


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

我只想在is 时JsonIgnore()Test2List属性添加属性。如果它不为null,那么我想将其包含在json中。Test2Listnull

Answers:


685

根据James Newton King的说法:如果您自己创建序列化程序而不是使用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,new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
阿米特(Amit)

它为我工作,但我不得不使用JsonSerializerSettingsJsonSerializer因为它表明最后一个错误
Yazan

1
一件重要的事情-它仅适用于具体的类(人员,帐户等)。当我用Dictionary尝试此操作时,它不起作用
chester89

1
我和@ chester89有同样的问题。使用ExpandoObject时,不会忽略null值。这似乎是一个错误(使用json.net 9.0.1)
kwrl '16

2
编写答案时,JSON.Net甚至不支持动态对象。:)目前,您可以使用自定义转换器进行出价。
Mrchief '16

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
@Sergey取决于您的用例。如果只想将其用于特定属性(如问题中所述),那么这是正确的答案。如果需要全局答案,则应在JsonSerializer中设置属性。
sibbl

同意-这是简单而优雅的。值得投票。效果很好-只需在要序列化的对象中将属性设置为VB中的Nothing即可,它不再是JSON的一部分。不过,这仅适用于字符串。枚举或整数属性将始终显示-设置为Nothing不会导致默认值“ 0”。
Destek

3
@Destek,您需要使引用类型字段可为空,然后它们将不会使用属性或设置进行序列化。
托尼

1
为了避免“污染”具有许多属性的类,您还可以在上分配处理规则[JsonObject],但请注意,属性名称不同。[已编辑答案]
Simon_Weaver

60

类似@ sirthomas的回答,也JSON.NET尊重EmitDefaultValue特性DataMemberAttribute

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

如果你已经使用了,这可能是可取的[DataContract],并[DataMember]在模型类型,不希望添加JSON.NET特定的属性。


1
这很有帮助!我正在设计一个自定义的Exception类,并且不想在其中添加Json.net。谢谢!
jpgrassi 2015年

2
这在.Net Core中不起作用。推荐@sirthomas答案:使用[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
Derrick

1
对于Newton.Json 10.0.2,在.Net Core中对我来说效果很好。
Karl-JohanSjögren'17

33

你可以写: [JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]

它还注意不要使用默认值(不仅是null)来序列化属性。例如,它对于枚举很有用。


3
这与irirmas的答案完全相同,为什么要添加它呢?
OMGtechy

4
对于您的信息,DefaultValueHandling和NullValueHandling ...之间是有区别的
Vatsal Patel

4
那你能在回答中解释一下吗?乍一看,它看起来是一样的,现在您已经提到了,它并没有说明这与其他答案有何不同/它如何称赞它。
OMGtechy

1
尽管在某些情况下可接受的答案可能有用,但并非总是可以使用它。这就是医生的命令。
墨尔本开发商

1
我想这就是我想要的。对某些属性(不是全部)的特定处理。
frostymarvelous

23

您可以执行此操作以忽略要序列化的对象中的所有null,并且所有null属性都不会出现在JSON中

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

12

从他们网站(http://james.newtonking.com/archive/2009/10/23/efficiency-json-with-json-net-reducing-serialized-json-size.aspx)的链接中可以看出支持使用[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并不总是“显而易见”),您还可以装饰单个类的属性来管理如何处理空值。如果这样做,请不要使用GlennG建议中的全局JsonSerializerSettings,否则它将覆盖各个装饰。如果您希望在JSON中显示一个空项目,则此方法很方便,这样使用者就不必进行任何特殊处理。例如,如果消费者需要知道通常有可用的可选项目数组,但是当前为空...属性声明中的修饰如下所示:

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

对于这些属性,您根本不想在JSON更改中出现:== NullValueHandling.Include:= NullValueHandling.Ignore。顺便说一句-我发现您可以很好地装饰XML和JSON序列化的属性(只需将它们彼此紧靠在一起即可)。这使我可以选择在dotnet中调用XML序列化器,也可以随意调用NewtonSoft序列化器-两者并排工作,我的客户可以选择使用XML或JSON。因为我有同时需要这两个功能的客户,所以在门把手上像as鼻涕一样光滑!


0

这是一个类似的选项,但提供了另一个选择:

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

然后,我像这样使用它:

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

这里的区别是:

  • 通过实例化和配置JsonSerializerSettings每个使用位置来减少重复的代码。
  • 节省配置要序列化的每个对象的每个属性的时间。
  • 仍然为其他开发人员提供了序列化选项方面的灵活性,而不是在可重用对象上显式指定了属性。
  • 我的用例是该代码是第3方库,并且我不想对希望重用我的类的开发人员强加序列化选项。
  • 潜在的缺点是,这是其他开发人员需要了解的另一个对象,或者您的应用程序是否较小,并且这种方法对于单个序列化都没有关系。

-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。忽略其他答案 不清楚,您的答案有什么新变化
Michael Freidgeim
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.