• 踩坑System.Text.Json日期格式化


    最近把项目中用到的Json序列化组件由Newtonsoft.Json改为.net自带的System.Text.Json,本以为对于轻度使用来说可以无缝切换的,万万没想到这两个库的默认行为还是有些不同的。

    以下面的实体类为例,说一下我的填坑过程。

    class Test
    {
        public string AccountName { get; set; }
        public DateTime RegisterTime { get; set; }
    }
    
    var testObj = new Test() { AccountName = "admin@江苏", RegisterTime = new DateTime(2021, 10, 1, 10, 10, 10) };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    后端用golang搭建的服务,对于日期字段要求使用2006-01-02T15:04:05+07:00格式,此前用Newtonsoft.Json很顺利,在序列化参数中指定日期格式即可,可用如下方式全局指定,也可在每次调用序列化方法时作为参数传入。

    Newtonsoft.Json.JsonConvert.DefaultSettings = () =>
    {
        return new Newtonsoft.Json.JsonSerializerSettings()
        {
            DateFormatString = "yyyy-MM-ddTHH:mm:sszzzz"
        };
    };
    var str = Newtonsoft.Json.JsonConvert.SerializeObject(testObj);
    Console.WriteLine(str);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    输出结果为:

    {"AccountName":"admin@江苏","RegisterTime":"2021-10-01T10:10:10+08:00"}
    
    • 1

    然而System.Text.Json中找不到能全局指定参数的方法,需要每次在序列化的时候传入,根据网上的资料很容易写出下面的使用方法。

    /// 
    /// 设置Json默认DateTime格式
    /// 
    public class DateTimeJsonConverter : System.Text.Json.Serialization.JsonConverter
    {
        private readonly string _Format;
        public DateTimeJsonConverter(string format)
        {
            _Format = format;
        }
        public override void Write(Utf8JsonWriter writer, DateTime date, JsonSerializerOptions options)
        {
            writer.WriteStringValue(date.ToString(_Format));
        }
        public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return DateTime.ParseExact(reader.GetString(), _Format, null);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    JsonSerializerOptions jsonSerializerSettings = new JsonSerializerOptions()
    {
        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
        PropertyNameCaseInsensitive = true,
    };
    jsonSerializerSettings.Converters.Add(new DateTimeJsonConverter("yyyy-MM-ddTHH:mm:sszzzz"));
    
    str = System.Text.Json.JsonSerializer.Serialize(testObj, jsonSerializerSettings);
    Console.WriteLine(str);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    此时输出如下:

    {"AccountName":"admin@\u6C5F\u82CF","RegisterTime":"2021-10-01T10:10:10\u002B08:00"}
    
    • 1

    不仅中文被显示为unicode编码,日期中的+也没能不对,导致后端无法识别。

    在网上找到了赵明庆老师的博客【原创】使用System.Text.Json对Json字符串进行格式化_赵庆明老师的博客-CSDN博客_system.text.json,根据文章在序列化参数中添加了一行代码。

    new JsonSerializerOptions()
    {
        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
        PropertyNameCaseInsensitive = true,
        //重新编码,解决中文乱码问题
        Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    输出如下,中文能正常显示了,可日期还是不对。

    {"AccountName":"admin@江苏","RegisterTime":"2021-10-01T10:10:10\u002B08:00"}
    
    • 1

    最终翻阅MSDN,终于在如何使用 System.Text.Json 自定义字符编码 | Microsoft Learn中找到了解决办法,输出与之前使用Newtonsoft.Json一致了。

    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
    
    • 1

    2022年10月21日星期五

  • 相关阅读:
    nginx配置-gzip
    c语言编程请增补函数fun
    linux系统维护篇:网络流量查看及带宽测试
    【题解】同济线代习题一.6.5
    centos 安装 percona-xtrabackup
    matplotlib制图初级篇
    【附源码】计算机毕业设计JAVA传统文化知识竞赛系统
    P2602数字计数
    关于FFmepg的冷知识,这一篇就够了
    《Reinforcement Learning: An Introduction》第8章笔记
  • 原文地址:https://blog.csdn.net/szaf59313/article/details/127450649