You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何捕获NewtonSoft.Json中的JsonSerializationException非致命异常?

Newtonsoft.Json反序列化非致命异常问题

问题现象

使用NewtonSoft.Json自定义转换器反序列化JSON文件时,控制台大量输出重复异常:

Exception thrown: 'Newtonsoft.Json.JsonSerializationException' in Newtonsoft.Json.dll

尝试用try/catch无法捕获该异常,但反序列化最终成功完成,能得到正确的对象。

疑问

  1. 这些非致命异常的来源是什么?
  2. 是否需要处理这类异常?
  3. 如何捕获并记录这些异常?
  4. 是否可以重写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

若要消除控制台的异常输出,可调整调试器设置:

  1. 打开Visual Studio的「调试」->「窗口」->「异常设置」
  2. 展开「Common Language Runtime Exceptions」,找到Newtonsoft.Json.JsonSerializationException
  3. 取消勾选「抛出时」的捕获选项,调试器就不会输出已被处理的该类异常

是否可以重写JsonSerializationException

不需要重写该异常类。Json.NET的ErrorEventArgs已经提供了完整的错误上下文(错误信息、路径、对象等),你只需在Error事件中处理即可。若需自定义异常,可在事件中根据错误信息抛出,但这会终止反序列化,不符合当前需求。

额外优化建议

  1. 优化ObjectFileConverter的文本替换逻辑,尽量提前修正JSON中的类型名称或格式错误,减少反序列化时的异常触发。
  2. 在MySerializationBinder的BindToType中覆盖更多类型场景,减少调用base.BindToType时的失败概率。

内容的提问来源于stack exchange,提问作者stackMeUp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 17:15:37