踩坑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) };

后端用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);

输出结果为:

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

然而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);
    }
}
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);

此时输出如下:

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

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

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

new JsonSerializerOptions()
{
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
    PropertyNameCaseInsensitive = true,
    //重新编码,解决中文乱码问题
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
}

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

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

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

Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping

2022年10月21日星期五

你可能感兴趣的:(程序人生,json,c#)