如何记录Newtonsoft.Json/System.Text.Json的静默反序列化问题?
直接通过序列化库拦截的方案
Newtonsoft.Json(Json.NET)
启用严格模式捕获缺失属性
修改JsonSerializerSettings,将MissingMemberHandling设为MissingMemberHandling.Error,反序列化时遇到目标类不存在的属性会直接抛出JsonSerializationException,而非静默忽略:var settings = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Error }; var obj = JsonConvert.DeserializeObject<T>(json, settings);利用Error事件捕获类型转换等静默问题
即使库尝试自动转换类型(如字符串"true"转bool),也可通过Error事件捕获转换过程中的异常或警告,记录详细信息:var settings = new JsonSerializerSettings(); settings.Error += (sender, args) => { Log.Error($"反序列化错误:路径{args.ErrorContext.Path},原因{args.ErrorContext.Error.Message}"); // 若不想中断序列化,可设置args.ErrorContext.Handled = true; }; var obj = JsonConvert.DeserializeObject<T>(json, settings);
System.Text.Json
启用缺失成员报错
配置JsonSerializerOptions的MissingMemberHandling为JsonMissingMemberHandling.Error,强制对未匹配的属性抛出异常:var options = new JsonSerializerOptions { MissingMemberHandling = JsonMissingMemberHandling.Error }; var obj = JsonSerializer.Deserialize<T>(json, options);自定义转换器捕获类型转换问题
System.Text.Json默认对类型转换更严格(如无法直接将字符串"true"转bool),若需兼容这类场景同时记录转换行为,可自定义转换器:public class StrictBooleanConverter : JsonConverter<bool> { public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) { Log.Warn($"路径{reader.CurrentState.Path}:将字符串{reader.GetString()}转换为bool"); return bool.Parse(reader.GetString()!); } return reader.GetBoolean(); } public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options) { writer.WriteBooleanValue(value); } }使用时将转换器加入
JsonSerializerOptions:var options = new JsonSerializerOptions(); options.Converters.Add(new StrictBooleanConverter());
额外监控与维护策略
反序列化后数据验证
反序列化完成后对对象进行完整性校验:检查必填属性是否为非默认值、枚举值是否合法等。可使用FluentValidation简化校验逻辑,或手动编写反射遍历属性的校验代码。日志对比审计
记录原始JSON字符串和反序列化后的对象快照(如重新序列化为JSON),通过自动化工具或人工抽查,发现属性缺失、类型转换导致的数据偏差。版本化数据契约
针对不同版本的JSON结构,定义对应的DTO类(如UserV1Dto、UserV2Dto),避免跨版本兼容导致的静默转换问题。同时在传输层明确版本标识,确保双方使用匹配的契约。自定义契约校验器
编写独立的JSON Schema校验逻辑,在序列化/反序列化前先对原始JSON进行Schema验证,提前发现结构不匹配、类型错误等问题,再进行后续对象转换。
内容的提问来源于stack exchange,提问作者Banshee

