关于c#:如何使用json.net忽略类中的属性null

How to ignore a property in class if null, using json.net

我正在使用Json.NET将类序列化为JSON。

我有这样的课:

1
2
3
4
5
6
7
8
9
10
11
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; }
}

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


使用JsonProperty属性的备用解决方案:

1
2
3
4
5
6
[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
// or
[JsonProperty("property_name", NullValueHandling=NullValueHandling.Ignore)]

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

正如在线文档中所见。


根据James Newton King的说法:如果您自己创建序列化程序而不是使用JavaScriptConvert,则可以设置NullValueHandling属性,您可以将其设置为忽略。

这是一个示例:

1
2
3
JsonSerializer _jsonWriter = new JsonSerializer {
                                 NullValueHandling = NullValueHandling.Ignore
                             };

或者,正如@amit所建议的那样

1
2
3
4
5
JsonConvert.SerializeObject(myObject,
                            Newtonsoft.Json.Formatting.None,
                            new JsonSerializerSettings {
                                NullValueHandling = NullValueHandling.Ignore
                            });


与@ sirthomas的答案类似,JSON.NET也尊重DataMemberAttribute上的EmitDefaultValue属性:

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

如果您已在模型类型中使用[DataContract][DataMember]并且不想添加特定于JSON.NET的属性,则可能需要这样做。


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

它还负责不使用默认值(不仅为null)序列化属性。例如,它可用于枚举。


您可以这样做来忽略您正在序列化的对象中的所有空值,然后任何空属性都不会出现在JSON中

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

可以在他们网站上的这个链接中看到(http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx)我支持使用[Default()]指定默认值

取自链接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
   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
// }


适应@Mychief的/ @ amit的答案,但适用于使用VB的人

1
2
3
4
5
6
 Dim JSONOut As String = JsonConvert.SerializeObject(
           myContainerObject,
           New JsonSerializerSettings With {
                 .NullValueHandling = NullValueHandling.Ignore
               }
  )

看到:
"对象初始化器:命名和匿名类型(Visual Basic)"

https://msdn.microsoft.com/en-us/library/bb385125.aspx


用Json.NET

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 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 });

结果将是:

1
2
3
4
{
  "Name":"Bad Boys III",
  "Description":"It's no Bad Boys"
 }

在.Net Core中,现在这更容易了。在你的startup.cs中只需添加json选项,你就可以在那里配置设置。

1
2
3
4
5
6
7
8
public void ConfigureServices(IServiceCollection services)

....

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

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

1
2
3
4
5
6
7
public class DefaultJsonSerializer : JsonSerializerSettings
{
    public DefaultJsonSerializer()
    {
        NullValueHandling = NullValueHandling.Ignore;
    }
}

然后,我像这样使用它:

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

这里的区别在于:

  • 通过实例化和配置JsonSerializerSettings每个使用的位置来减少重复的代码。
  • 节省配置每个要序列化的对象的每个属性的时间。
  • 仍然为其他开发人员提供了序列化选项的灵活性,而不是在可重用对象上明确指定属性。
  • 我的用例是代码是第三方库,我不想对想要重用我的类的开发人员强制使用序列化选项。
  • 潜在的缺点是,这是其他开发人员需要了解的另一个对象,或者如果您的应用程序很小,这种方法对于单个序列化无关紧要。

稍微阐述一下GlennG非常有用的答案(将语法从C#转换为VB.Net并不总是"显而易见"),您还可以修饰单个类属性来管理如何处理空值。如果这样做,请不要使用GlennG建议的全局JsonSerializerSettings,否则它将覆盖单个装饰。如果您希望在JSON中显示空项目,那么这会派上用场,因此消费者不必进行任何特殊处理。例如,如果消费者需要知道一系列可选项目通常是可用的,但目前是空的......
属性声明中的装饰如下所示:

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

对于那些您不希望在JSON更改中出现的属性:= NullValueHandling.Include to:= NullValueHandling.Ignore。
顺便说一句 - 我发现你可以为XML和JSON序列化装饰一个属性就好了(只需将它们放在彼此旁边)。这使我可以随意调用dotnet中的XML序列化程序或NewtonSoft序列化程序 - 两者并排工作,我的客户可以选择使用XML或JSON。由于我的顾客需要两者,所以这就像门把手上的鼻涕一样光滑!


1
2
3
4
5
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);