.NET Core 处理 WebAPI JSON 返回烦人的null为空

前言

项目开发中不管是前台还是后台都会遇到烦人的 null,数据库表中字段允许空值,则代码实体类中对应的字段类型为可空类型 Nullable<>,如 int?,DateTime?,null 值字段序列化返回的值都为 null,前台对应字段赋值需要做 null 值判断,怎么才能全局把 null 替换为空。

本文分享 WebAPI 接口服务统一返回 null 替换为空的方法。

一、分析问题 

.NET Core 中使用 Newtonsoft.Json 进行序列化,WebAPI 接口返回格式通过 Startup.cs 类全局设置。想是否可以通过配置把 null 替换为空值?于是找到了 Newtonsoft.Json 在序列化和反序列化期间如何处理空值和默认值的属性,具体配置代码如下:

public void ConfigureServices(IServiceCollection services)
{
    //配置 Mvc + json 序列化
    services.AddMvc()
        .AddNewtonsoftJson(options =>
        {
            //数据格式首字母小写 不使用驼峰  
            options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            //使用默认方式,不更改元数据的 key 的大小写
            //options.SerializerSettings.ContractResolver = new DefaultContractResolver();
            // 忽略循环引用
            options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            // 设置时间格式
            options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
            //忽略空值 不包含属性的 null 序列化
            //options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
            //忽略默认值和 null  1、不包含属性默认值和 null
            //options.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Igno
        })
}

 

1、空值的处理

序列化和反序列化时需要忽略值为 null 的属性,设置 NullValueHandling 的值

  • NullValueHandling.Ignore 序列化和反序列化对象时忽略空值

  • NullValueHandling.Include 序列化和反序列化对象时包含空值 

2、默认值的处理

序列化和反序列化时需要忽略默认值属性,设置 DefaultValueHandling 的值

  • DefaultValueHandling.Ignore 序列化和反序列化时忽略默认值

  • DefaultValueHandling.Include 序列化和反序列化时包含默认值

3、示例代码

通过上面的分析:一种是不包含属性的默认值序列化,另一种是不包含属性的 null 序列化,都不能满足目前的需求接口统一返回的 null 序列化为空。

/*包含属性的默认值与 null 序列化*/
{
  "Name": null,
  "NickName": null,
  "Age": 0,
  "Sex": 0
}
/*不包含属性的默认值序列化*/
{
  "Name": "Hello World",
  "Age": 24
}
/*不包含属性的 null 序列化*/
{
  "Name": "Hello World",
  "Age": 28,
  "Sex": 0
}

 二、解决问题

 1、项目 WebAPI 默认返回的 JSON 结果格式如下:

{
  "code": 0,
  "msg": "查询成功",
  "data": {
    "id": 1,
    "title": "炎炎夏日暖暖肚",
    "describe": "",
    "author": null,
    "authorId": null,
    "linkSource": null,
    "author_Picture": null,
    "content": "炎炎夏日,很多人喜欢吃些寒凉的食物解暑,可这种做法非常伤身。",
  }
}

 2、需要解决的问题把所有的 null 替换为空,具体如下图所示:

.NET Core 处理 WebAPI JSON 返回烦人的 null 为空

3、解决方案

需要自己写一个 NullToEmptyStringResolver 类,然后重写 CamelCasePropertyNamesContractResolver,但是该方法只能解决 string 类型 null→””的问题,对其他可空类型无效,比如:int?、DateTime?等。

public class NullToEmptyStringResolver : CamelCasePropertyNamesContractResolver
{
    /// <summary>
    /// 创建属性
    /// </summary>
    /// <param name="type">类型</param>
    /// <param name="memberSerialization">序列化成员</param>
    /// <returns></returns>
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        return type.GetProperties().Select(c =>
                {
                    var jsonProperty = base.CreateProperty(c, memberSerialization);
                    jsonProperty.ValueProvider = new NullToEmptyStringValueProvider(c);
                    return jsonProperty;
                }).ToList();
    }
}

public class NullToEmptyStringValueProvider : IValueProvider
{
    private readonly PropertyInfo _memberInfo;
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="memberInfo"></param>
    public NullToEmptyStringValueProvider(PropertyInfo memberInfo)
    {
        _memberInfo = memberInfo;
    }

    /// <summary>
    /// 获取 Value
    /// </summary>
    /// <param name="target"></param>
    /// <returns></returns>
    public object GetValue(object target)
    {
        var result = _memberInfo.GetValue(target);
        if (_memberInfo.PropertyType == typeof(string) && result == null)
            result = string.Empty;
        return result;
    }

    /// <summary>
    /// 设置 Value
    /// </summary>
    /// <param name="target"></param>
    /// <param name="value"></param>
    public void SetValue(object target, object value)
    {
        _memberInfo.SetValue(target, value);
    }
}

 在 Startup.cs 代码里面修改,[options.SerializerSettings.ContractResolver = new NullToEmptyStringResolver();],如下所示:

//配置 MVC+JSON 序列化
services
    .AddMvc(options =>{options.EnableEndpointRouting = false;})
    .AddNewtonsoftJson(options =>
    {
        //使用默认方式,不更改元数据的 key 的大小写
        //options.SerializerSettings.ContractResolver = new DefaultContractResolver();
        //数据格式首字母小写 不使用驼峰   小驼峰 firstName  大驼峰 FirstName
        //options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        options.SerializerSettings.ContractResolver = new NullToEmptyStringResolver();
        // 忽略循环引用
        options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        // 设置时间格式
        options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
        //忽略空值 不包含属性的 null 序列化
        //options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
        //忽略默认值和 null  1、不包含属性默认值和 null 
        //options.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Igno
    })

 修改完配置,重新运行完成,实现 null 替换为空的效果,运行结果如下所示:

{
  "code": 0,
  "msg": "查询成功!",
  "data": {
    "id": 1,
    "title": "炎炎夏日暖暖肚",
    "describe": "",
    "author": "",
    "authorId": "",
    "linkSource": "",
    "author_Picture": "",
    "source": 0,
    "content": "炎炎夏日,很多人喜欢吃些寒凉的食物解暑,可这种做法非常伤身。"
  }
}

 三、总结

 .NET Core 下 Newtonsoft.Json 序列化时字符串 null 替换成空,通过 ContractResolver 类为属性添加一些序列化设置、自定义属性名、设置时间格式、有选择性的序列化属性等,实现 WebAPI 返回 JSON 格式统一化。

© 版权声明

☆ END ☆
喜欢就点个赞吧
点赞0 分享
图片正在生成中,请稍后...