最近把项目中用到的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日星期五