• .NET WebAPI 自定义 NullableConverter 解决可为空类型字段入参“”空字符触发转换异常问题


    最近在项目中启用了Nullable 可为空的类型,这个特性确实很好用,在 WebAPI 的入参上可以直接采用 ? 来标记一个字段是否允许为空,但是使用过程中遇到了如下一个问题,比如创建部门接口

    我们定义入参模型如下:

    public class DtoDepartment
    {
        /// 
        /// 部门名称
        /// 
        public string Name { get; set; }
    
        /// 
        /// 上级部门ID
        /// 
        public Guid? ParentId { get; set; }
    }
    

    我们这里将上级部门ID定义为可以为空的类型,因为有些部门不存在上级部门
    然后定义这样一个接口

    [HttpPost("CreateDepartment")]
    public bool CreateDepartment(DtoDepartment department)
    {
        //省略业务逻辑
        return true;
    }
    

    当前端请求的时候传入如下Json 时则就会触发异常

    {
      "name": "商务一部",
      "parentId": ""
    }
    

    异常内容为:

    {
      "errMsg": "The department field is required. | The JSON value could not be converted to System.Nullable`1[System.Guid]. Path: $.parentId | LineNumber: 2 | BytePositionInLine: 16."
    }
    

    像这样的情况是因为虽然我们定义的 Dto 允许上级部门ID字段为空,但是前端调用的时候 parentId 实际传入的是 "" 空字符串,当空字符串给 Guid? 转换的时候就会产生这样的异常,当遇到这样的情况时,我们可以要求前端调整 JSON 格式如下

    {
      "name": "商务一部",
      "parentId": null
    }
    

    前端只要给 parentId 的赋值从 "" 调整为 null 之后我们的接口就可以正常运行了,但是有的时候前端的组件这里取值可能是和一些组件库绑定的,不太方便绑定默认值为 null,很多情况下组件库组件的默认值都是 "" 空字符串的形式,所以经过和前端同事多次沟通之后想着从后端彻底解决这个问题,经过研究之后编写了下面的 NullableConverter 转换器,只要在项目启动的时候注册到 AddJsonOptions 其中即可。

    using System.Text.Json;
    using System.Text.Json.Serialization;
    
    namespace Common.JsonConverter
    {
        public class NullableConverter<T> : JsonConverter<T?> where T : struct
        {
    
            public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
            {
                if (reader.TokenType == JsonTokenType.String)
                {
                    if (string.IsNullOrEmpty(reader.GetString()) || string.IsNullOrWhiteSpace(reader.GetString()))
                    {
                        return null;
                    }
                }
                return JsonSerializer.Deserialize(ref reader, options);
            }
    
    
            public override void Write(Utf8JsonWriter writer, T? value, JsonSerializerOptions options)
            {
                JsonSerializer.Serialize(writer, value!.Value, options);
            }
    
        }
    }
    

    上面我们只是用 Guid? 举了一个例子,实际情况下

    • DateTime?
    • DateTimeOffset?
    • long?
    • int?
    • double?
    • decimal?
    • float?
    • Guid?
    • bool?

    都有可能存在这个问题,所以我们为这几种类型都配置了这个可为空类型转换器。这样前端在调用接口时配到这类型的字段,传 "" 和 null 我们后端就都可以接收了,收到之后字段的值都是 null

    我这里项目采用的是微软的 System.Text.Json 处理的 Json 序列化,注册配置 NullableConverter 代码如下:

    #region 注册 Json 序列化配置
    builder.Services.AddControllers().AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Converters.Add(new Common.JsonConverter.NullableConverter());
        options.JsonSerializerOptions.Converters.Add(new Common.JsonConverter.NullableConverter());
        options.JsonSerializerOptions.Converters.Add(new Common.JsonConverter.NullableConverter());
        options.JsonSerializerOptions.Converters.Add(new Common.JsonConverter.NullableConverter());
        options.JsonSerializerOptions.Converters.Add(new Common.JsonConverter.NullableConverter());
        options.JsonSerializerOptions.Converters.Add(new Common.JsonConverter.NullableConverter());
        options.JsonSerializerOptions.Converters.Add(new Common.JsonConverter.NullableConverter());
        options.JsonSerializerOptions.Converters.Add(new Common.JsonConverter.NullableConverter());
        options.JsonSerializerOptions.Converters.Add(new Common.JsonConverter.NullableConverter());
    });
    #endregion
    

    至此 .NET WebAPI 自定义 NullableConverter 解决可为空类型字段入参“”空字符触发转换异常问题 就讲解完了,有任何不明白的,可以在文章下面评论或者私信我,欢迎大家积极的讨论交流,有兴趣的朋友可以关注我目前在维护的一个 .NET 基础框架项目,项目地址如下
    https://github.com/berkerdong/NetEngine.git
    https://gitee.com/berkerdong/NetEngine.git

  • 相关阅读:
    Maven历史版本下载
    Cadence Allegro PCB设计88问解析(十五) 之 Allegro中如何替换过孔类型
    GFLAGS中cmakeLists的编写-OsqpEigen中cmakeLists的编写---GLOG移植
    2021年全球最具吸引力的雇主:谷歌、微软、苹果占据前三名
    作业比赛编号 : 1276 - 2022年春季学期《算法分析与设计》练习14
    达梦数据库使用中遇到的问题和解决方案
    云原生是整个信息化行业的未来,一文彻底搞懂云原生
    list用stream流转map报key重复
    大数据开发面试笔记Day1
    42. QT中开发Android配置QFtp功能时遇到的编译问题
  • 原文地址:https://www.cnblogs.com/berkerdong/p/16712772.html