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; } } |
我想仅在
使用
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,则可以设置
这是一个示例:
1 2 3 |
或者,正如@amit所建议的那样
1 2 3 4 5 | JsonConvert.SerializeObject(myObject, Newtonsoft.Json.Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }); |
与@ sirthomas的答案类似,JSON.NET也尊重
1 | [DataMember(Name="property_name", EmitDefaultValue=false)] |
如果您已在模型类型中使用
你可以写:
它还负责不使用默认值(不仅为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 |
这里的区别在于:
-
通过实例化和配置
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); |