迁移至System.Text.Json:如何处理嵌套序列化DateTime的格式转换?
解决方法
1. 强类型处理(推荐,更安全)
既然SerializedClass本来就是OtherClass的序列化结果,直接反序列化成OtherClass实例,再用配置好的JsonSerializerOptions重新序列化,就能自动把DateTime格式修正过来:
// 配置序列化选项:指定DateTime格式为三位毫秒带Z,保持驼峰命名(如果原JSON是驼峰格式的话) var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, DateTimeFormat = new DateTimeFormatInfo { FullDateTimePattern = "yyyy-MM-dd'T'HH:mm:ss.fffZ" } }; // 处理你的MyClass对象 var myClass = ...; // 你的MyClass实例 // 把SerializedClass反序列成OtherClass var otherObj = JsonSerializer.Deserialize<OtherClass>(myClass.SerializedClass, options); // 重新序列化回字符串,此时DateTime的多余零已经被去掉 myClass.SerializedClass = JsonSerializer.Serialize(otherObj, options);
要是需要更灵活的DateTime控制,也可以自定义转换器:
public class DateTimeTrimmingConverter : JsonConverter<DateTime> { private const string TargetFormat = "yyyy-MM-dd'T'HH:mm:ss.fffZ"; public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 读取时兼容原格式,不管末尾有几个零,自动识别 return DateTime.Parse(reader.GetString()!, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); } public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) { // 写入时强制输出三位毫秒的格式 writer.WriteStringValue(value.ToString(TargetFormat, CultureInfo.InvariantCulture)); } } // 然后在options里添加这个转换器: options.Converters.Add(new DateTimeTrimmingConverter());
2. 动态JSON操作(类似Newtonsoft的JObject)
如果不想用强类型,要像JObject那样动态操作JSON,在.NET 6及以上版本可以用JsonObject(属于JsonNode体系),结合配置好的选项序列化就能修正格式:
var options = new JsonSerializerOptions { DateTimeFormat = new DateTimeFormatInfo { FullDateTimePattern = "yyyy-MM-dd'T'HH:mm:ss.fffZ" } }; // 把SerializedClass解析成JsonObject,就能像JObject一样动态修改字段 var jsonObj = JsonNode.Parse(myClass.SerializedClass) as JsonObject; // 这里可以做任意JSON操作,比如修改某个字段:jsonObj["someKey"] = "newValue"; // 重新序列化时用配置好的options,DateTime格式会自动修正 myClass.SerializedClass = jsonObj!.ToJsonString(options);
为什么之前自定义DateTime转换器没用?
因为你之前是直接解析字符串(SerializedClass),而不是反序列化为包含DateTime字段的类型。只有当反序列化的目标类型里有DateTime字段时,转换器才会被触发。上面两种方案要么反序列成强类型OtherClass(触发转换器),要么解析成JsonNode后,通过序列化选项的配置来统一处理DateTime格式。
注意事项
JsonNode(包括JsonObject)是.NET 6才新增的API,如果你用的是更早的.NET版本,得用JsonElement,但操作起来没那么方便,还是升级到.NET 6+更省心。- 配置
fff格式刚好对应三位毫秒,完美匹配你要的输出格式。 - 读取DateTime时用
DateTimeStyles.RoundtripKind可以保留原时间的Utc标记,避免序列化时出现时区偏移问题。
内容的提问来源于stack exchange,提问作者Gil
相关产品推荐
相关产品推荐

