如何捕获NewtonSoft.Json中的JsonSerializationException非致命异常?
Newtonsoft.Json反序列化非致命异常问题
问题现象
使用NewtonSoft.Json自定义转换器反序列化JSON文件时,控制台大量输出重复异常:
Exception thrown: 'Newtonsoft.Json.JsonSerializationException' in Newtonsoft.Json.dll
尝试用try/catch无法捕获该异常,但反序列化最终成功完成,能得到正确的对象。
疑问
- 这些非致命异常的来源是什么?
- 是否需要处理这类异常?
- 如何捕获并记录这些异常?
- 是否可以重写
JsonSerializationException?
代码背景
顶层调用代码
// 调用自定义转换器的顶层代码 var MyConvolutedObject= JsonConvert.DeserializeObject<ConvolutedObjectType>( File.ReadAllText(pathToSerializedObject), new MyCustomConverter());
自定义转换器代码
namespace MyNamespace { public class MySerializationBinder : DefaultSerializationBinder { private string _context; public MySerializationBinder(string context) { _context = context; } public override Type BindToType(string assemblyName, string typeName) { // 一些类型替换逻辑 switch (typeName.ToLower()) { case "bool": return typeof(...); case "int": case "int32": return typeof(...); default: return base.BindToType(assemblyName, typeName); } } } public class MyCustomConverter : JsonConverter { protected string ObjectFileConverter(string objectFile) { // 对JSON文本做替换,修正格式以适配反序列化 // ...... return objectFile; } public override bool CanConvert(Type objectType) { return typeof(ConvolutedObjectType).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo()); } static List<string> errors = new List<string>(); static readonly JsonSerializerSettings _jsonSettings = new JsonSerializerSettings { Error = delegate (object sender, ErrorEventArgs args) { errors.Add(args.ErrorContext.Error.Message); args.ErrorContext.Handled = true; }, TypeNameHandling = TypeNameHandling.All, ObjectCreationHandling = ObjectCreationHandling.Replace, PreserveReferencesHandling = PreserveReferencesHandling.Objects, SerializationBinder = new MySerializationBinder("Context") }; public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JToken token = JToken.Load(reader); string adaptedObject = token.ToString(); // 文本替换修正格式 adaptedObject = ObjectFileConverter(adaptedObject); return JsonConvert.DeserializeObject<ConvolutedObjectType>(adaptedObject, _jsonSettings); } public override bool CanWrite { get { return false; } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } } }
问题分析与解决方案
异常来源
这些异常是Json.NET内部在反序列化过程中抛出的可恢复错误,常见场景包括:
MySerializationBinder调用base.BindToType时类型绑定失败- 文本替换后的JSON仍存在局部字段类型不匹配
- 其他序列化过程中的非致命格式问题
try/catch抓不到是因为你在_jsonSettings的Error事件中设置了args.ErrorContext.Handled = true,Json.NET会捕获这些异常并继续反序列化;而控制台的输出是调试器的默认行为——它会捕获所有抛出的异常(即使已被程序处理)。
是否需要处理
- 如果最终反序列化结果正确,且这些异常是你预期内的(比如类型绑定的 fallback 逻辑、文本替换的残留问题),可以不用处理。
- 如果异常数量过多或包含未知错误,建议收集错误日志排查,避免潜在的序列化逻辑漏洞。
如何捕获异常
你已通过Error事件收集错误,但当前errors是静态字段,会累积多次反序列化的错误,建议优化为实例字段:
public class MyCustomConverter : JsonConverter { private List<string> _errors = new List<string>(); private readonly JsonSerializerSettings _jsonSettings; public MyCustomConverter() { _jsonSettings = new JsonSerializerSettings { Error = (sender, args) => { _errors.Add(args.ErrorContext.Error.Message); args.ErrorContext.Handled = true; }, TypeNameHandling = TypeNameHandling.All, ObjectCreationHandling = ObjectCreationHandling.Replace, PreserveReferencesHandling = PreserveReferencesHandling.Objects, SerializationBinder = new MySerializationBinder("Context") }; } // 提供获取错误的方法 public List<string> GetDeserializationErrors() { return new List<string>(_errors); } // 其他代码不变 }
顶层调用时可获取并处理错误:
var converter = new MyCustomConverter(); var myObject = JsonConvert.DeserializeObject<ConvolutedObjectType>( File.ReadAllText(pathToSerializedObject), converter); var errors = converter.GetDeserializationErrors(); // 记录或处理errors
若要消除控制台的异常输出,可调整调试器设置:
- 打开Visual Studio的「调试」->「窗口」->「异常设置」
- 展开「Common Language Runtime Exceptions」,找到
Newtonsoft.Json.JsonSerializationException - 取消勾选「抛出时」的捕获选项,调试器就不会输出已被处理的该类异常
是否可以重写JsonSerializationException
不需要重写该异常类。Json.NET的ErrorEventArgs已经提供了完整的错误上下文(错误信息、路径、对象等),你只需在Error事件中处理即可。若需自定义异常,可在事件中根据错误信息抛出,但这会终止反序列化,不符合当前需求。
额外优化建议
- 优化
ObjectFileConverter的文本替换逻辑,尽量提前修正JSON中的类型名称或格式错误,减少反序列化时的异常触发。 - 在
MySerializationBinder的BindToType中覆盖更多类型场景,减少调用base.BindToType时的失败概率。
内容的提问来源于stack exchange,提问作者stackMeUp
相关产品推荐
相关产品推荐

