为何自定义System.Text.Json.DateTime转换器会触发可空DateTime属性读取?
问题根因
System.Text.Json 对可空值类型(Nullable<T>/T?)有内置适配逻辑:当处理T?类型的属性时,只要属性值不为null,序列化器会自动剥离Nullable<>的外层包装,使用对应非可空类型T的匹配转换器处理实际值,这就是你仅适配了DateTime的转换器会被DateTime?属性触发执行的原因。你观察到的第5次CanConvert调用,就是序列化器处理DateTime?属性内部非空值时发起的类型检测。
当JSON里Expired字段传null时,序列化器会直接给属性赋值null,不会触发你的转换器逻辑,你不需要担心可空场景下的null返回问题。
修复方案
方案1:优化现有转换器逻辑(推荐,无需新增代码)
你现有转换器的Read方法只需要优化异常处理逻辑即可,不需要单独适配可空场景:
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TryGetDateTime(out var date)) { return date; } // 可替换为业务需要的自定义异常类型 throw new JsonException("无效的日期时间格式"); }
方案2:新增可空DateTime专属转换器(适用于有特殊处理需求的场景)
如果你对DateTime?类型有单独的处理逻辑,可以额外实现对应转换器,注册后序列化器会优先匹配精准类型的转换器:
public class UserBasedNullableDateTimeJsonConverter : JsonConverter<DateTime?> { private readonly UserBasedDateTimeJsonConverter _innerConverter; public UserBasedNullableDateTimeJsonConverter(IHttpContextAccessor httpContextAccessor) { _innerConverter = new UserBasedDateTimeJsonConverter(httpContextAccessor); } public override bool CanConvert(Type typeToConvert) { return typeof(DateTime?) == typeToConvert; } public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.Null) { return null; } return _innerConverter.Read(ref reader, typeof(DateTime), options); } public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) { if (value == null) { writer.WriteNullValue(); return; } _innerConverter.Write(writer, value.Value, options); } }
随后在CustomJsonOptions的Configure方法中注册该转换器即可:
public void Configure(JsonOptions options) { options.JsonSerializerOptions.Converters.Add(new UserBasedDateTimeJsonConverter(_accessor)); options.JsonSerializerOptions.Converters.Add(new UserBasedNullableDateTimeJsonConverter(_accessor)); }
额外提示:你现有代码里
CustomJsonOptions的构造方法名称写为了FeatureConfigJsonOptions,和类名不一致属于笔误,会触发编译错误,记得修正。
内容的提问来源于stack exchange,提问作者Rey
相关产品推荐
相关产品推荐

