.NET Core 處理 WebAPI JSON 返回煩人的null為空

Crazy Struggle發表於2021-01-12

前言

      專案開發中不管是前臺還是後臺都會遇到煩人的null,資料庫表中欄位允許空值,則程式碼實體類中對應的欄位型別為可空型別Nullable<>,如int?,DateTime?,null值欄位序列化返回的值都為null,前臺對應欄位賦值需要做null值判斷,怎麼才能全域性把null替換為空。

      本文分享WebAPI介面服務統一返回null替換為空的方法。

一、分析問題

      .NET Core中使用Newtonsoft.Json進行序列化,WebAPI介面返回格式通過Startup.cs類全域性設定。想是否可以通過配置把null替換為空值?於是找到了Newtonsoft.Json在序列化和反序列化期間如何處理空值和預設值的屬性,具體配置程式碼如下:

 1 public void ConfigureServices(IServiceCollection services)
 2 {
 3     //配置Mvc + json 序列化
 4     services.AddMvc()
 5         .AddNewtonsoftJson(options =>
 6         {
 7             //資料格式首字母小寫 不使用駝峰   小駝峰firstName  大駝峰 FirstName
 8             options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
 9             //使用預設方式,不更改後設資料的key的大小寫
10             //options.SerializerSettings.ContractResolver = new DefaultContractResolver();
11             // 忽略迴圈引用
12             options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
13             // 設定時間格式
14             options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
15             //忽略空值 不包含屬性的null序列化
16             //options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
17             //忽略預設值和null  1、不包含屬性預設值和null
18             //options.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Igno
19         })
20 }

 1、空值的處理

      序列化和反序列化時需要忽略值為null的屬性,設定SerializerSettings.NullValueHandling的值

  •  NullValueHandling.Ignore 序列化和反序列化物件時忽略空值。
  •  NullValueHandling.Include 序列化和反序列化物件時包含空值。

2、預設值的處理

      序列化和反序列化時需要忽略預設值屬性,設定SerializerSettings.DefaultValueHandling的值

  • DefaultValueHandling.Ignore 序列化和反序列化時忽略預設值
  • DefaultValueHandling.Include序列化和反序列化時包含預設值

3、示例程式碼

 1 /*包含屬性的預設值與null序列化*/
 2 {
 3   "Name": null,
 4   "Age": 0,
 5   "Partner": null,
 6   "Salary": 0.0
 7 }
 8 /*不包含屬性的預設值序列化*/
 9 {
10   "Name": "Hello World",
11   "Age": 28
12 }
13 /*不包含屬性的null序列化*/
14 {
15   "Name": "Hello World",
16   "Age": 28,
17   "Salary": 0.0
18 }

通過上面的分析:一種是不包含屬性的預設值序列化,另一種是不包含屬性的null序列化,都不能滿足目前的需求介面統一返回的null序列化為空。

二、解決問題

1、專案WebAPI預設返回的JSON結果格式如下:

 1 {
 2   "code": 0,
 3   "msg": "查詢成功",
 4   "data": {
 5     "id": 1,
 6     "title": "炎炎夏日暖暖肚",
 7     "describe": "",
 8     "author": null,
 9     "authorId": null,
10     "linkSource": null,
11     "author_Picture": null,
12     "content": "炎炎夏日,很多人喜歡吃些寒涼的食物解暑,可這種做法非常傷身。",
13   }
14 }

2、需要解決的問題把所有的null替換為空,具體如下圖所示:

      .NET Core 處理 WebAPI JSON 返回煩人的null為空  .NET Core 處理 WebAPI JSON 返回煩人的null為空

3、解決方案

      需要自己寫一個NullToEmptyStringResolver類,然後重寫CamelCasePropertyNamesContractResolver,但是該方法只能解決string型別null→""的問題,對其他可空型別無效,比如:int?、DateTime?等。

 1 public class NullToEmptyStringResolver : CamelCasePropertyNamesContractResolver
 2 {
 3     /// <summary>
 4     /// 建立屬性
 5     /// </summary>
 6     /// <param name="type">型別</param>
 7     /// <param name="memberSerialization">序列化成員</param>
 8     /// <returns></returns>
 9     protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
10     {
11         return type.GetProperties().Select(c =>
12                 {
13                     var jsonProperty = base.CreateProperty(c, memberSerialization);
14                     jsonProperty.ValueProvider = new NullToEmptyStringValueProvider(c);
15                     return jsonProperty;
16                 }).ToList();
17     }
18 }
19 
20 public class NullToEmptyStringValueProvider : IValueProvider
21 {
22     private readonly PropertyInfo _memberInfo;
23     /// <summary>
24     /// 建構函式
25     /// </summary>
26     /// <param name="memberInfo"></param>
27     public NullToEmptyStringValueProvider(PropertyInfo memberInfo)
28     {
29         _memberInfo = memberInfo;
30     }
31 
32     /// <summary>
33     /// 獲取Value
34     /// </summary>
35     /// <param name="target"></param>
36     /// <returns></returns>
37     public object GetValue(object target)
38     {
39         var result = _memberInfo.GetValue(target);
40         if (_memberInfo.PropertyType == typeof(string) && result == null)
41             result = string.Empty;
42         return result;
43     }
44 
45     /// <summary>
46     /// 設定Value
47     /// </summary>
48     /// <param name="target"></param>
49     /// <param name="value"></param>
50     public void SetValue(object target, object value)
51     {
52         _memberInfo.SetValue(target, value);
53     }
54 }

      在Startup.cs程式碼裡面修改,標記為紅色的程式碼,如下所示:

 1 //配置MVC+JSON序列化
 2 services
 3     .AddMvc(options =>{options.EnableEndpointRouting = false;})
 4     .AddNewtonsoftJson(options =>
 5     {
 6         //使用預設方式,不更改後設資料的key的大小寫
 7         //options.SerializerSettings.ContractResolver = new DefaultContractResolver();
 8         //資料格式首字母小寫 不使用駝峰   小駝峰firstName  大駝峰 FirstName
 9         //options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
10         options.SerializerSettings.ContractResolver = new NullToEmptyStringResolver();
11         // 忽略迴圈引用
12         options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
13         // 設定時間格式
14         options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
15         //忽略空值 不包含屬性的null序列化
16         //options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
17         //忽略預設值和null  1、不包含屬性預設值和null 
18         //options.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Igno
19     })

      修改完配置,重新執行完成,實現null替換為空的效果,執行結果如下所示:

 1 {
 2   "code": 0,
 3   "msg": "查詢成功!",
 4   "data": {
 5     "id": 1,
 6     "title": "炎炎夏日暖暖肚",
 7     "describe": "",
 8     "author": "",
 9     "authorId": "",
10     "linkSource": "",
11     "author_Picture": "",
12     "source": 0,
13     "content": "炎炎夏日,很多人喜歡吃些寒涼的食物解暑,可這種做法非常傷身。"
14   }
15 }

三、總結

      .NET Core下Newtonsoft.Json序列化時字串null替換成空,通過ContractResolver類為屬性新增一些序列化設定、自定義屬性名、設定時間格式、有選擇性的序列化屬性等,實現WebAPI返回JSON格式統一化。

 

優秀是一種習慣,歡迎大家關注學習  

 

相關文章