在NativeAOT C#应用中用源生成指定DateTime格式解析JSON
解决.NET 8 NativeAOT应用中DateTime反序列化失败问题
问题原因
System.Text.Json默认仅支持ISO 8601格式的日期字符串(如2024-05-30T09:17:26.003Z),而你传入的05/30/2024 09:17:26.003属于MM/dd/yyyy HH:mm:ss.fff格式,因此反序列化时抛出格式不匹配的异常。
方案1:通过JsonSourceGenerationOptions全局配置日期格式
直接在源生成配置中指定目标日期格式,让序列化上下文自动适配该格式,无需修改实体类:
[JsonSourceGenerationOptions( WriteIndented = true, DateFormatString = "MM/dd/yyyy HH:mm:ss.fff", DateTimeStyles = DateTimeStyles.AllowWhiteSpaces // 允许字符串中存在额外空白字符 )] [JsonSerializable(typeof(StateRequest))] [JsonSerializable(typeof(bool))] [JsonSerializable(typeof(string))] [JsonSerializable(typeof(DateTime))] public partial class StateRequestJsonContext : JsonSerializerContext { }
此方案适合所有DateTime类型属性都使用同一格式的场景,配置简单且全局生效。
方案2:自定义DateTime转换器(支持多格式或特定属性)
如果需要支持多种日期格式,或仅针对特定属性处理,可自定义转换器并集成到源生成上下文:
步骤1:实现自定义转换器
using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; public class CustomDateTimeConverter : JsonConverter<DateTime> { // 可根据需求添加更多支持的日期格式 private static readonly string[] _supportedFormats = { "MM/dd/yyyy HH:mm:ss.fff", "MM/dd/yyyy HH:mm:ss" }; public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.String) { throw new JsonException("预期字符串类型的日期值"); } var dateStr = reader.GetString(); if (DateTime.TryParseExact(dateStr, _supportedFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dateTime)) { return dateTime; } throw new JsonException($"无法解析日期:{dateStr},支持的格式为:{string.Join(", ", _supportedFormats)}"); } public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString(_supportedFormats[0], CultureInfo.InvariantCulture)); } }
步骤2:将转换器纳入源生成配置
修改JsonSourceGenerationOptions,让上下文识别并使用自定义转换器:
[JsonSourceGenerationOptions( WriteIndented = true, Converters = new[] { typeof(CustomDateTimeConverter) } )] [JsonSerializable(typeof(StateRequest))] [JsonSerializable(typeof(bool))] [JsonSerializable(typeof(string))] [JsonSerializable(typeof(DateTime))] public partial class StateRequestJsonContext : JsonSerializerContext { }
可选:仅针对特定属性应用转换器
如果只需处理StateRequest中的ClientTime属性,可直接在该属性上添加特性,无需修改全局配置:
public class StateRequest { [JsonConverter(typeof(CustomDateTimeConverter))] public DateTime ClientTime { get; set; } // 其他属性... }
注意事项
- 由于使用NativeAOT,所有Json转换器必须是具体类型且可被源生成器静态分析,避免使用依赖反射的动态转换器。
- 示例中使用
CultureInfo.InvariantCulture确保格式解析不受系统区域设置影响,若需适配特定语言环境,可替换为对应CultureInfo实例。
内容的提问来源于stack exchange,提问作者Alex Zaitsev
相关产品推荐
相关产品推荐

