如何手动触发Newtonsoft JsonSerialization错误并复现排查序列化异常
复现报错的方法
你遇到的MoveNextAction.Method.ReturnTypeCustomAttributes报错是序列化异步方法编译生成的内部状态机类时触发的,这类自动生成的类包含反射相关的不可序列化属性,可以用以下代码直接复现:
// 定义任意async方法 async Task TestAsync() => await Task.Delay(100); // 获取async方法生成的内部状态机实例 var task = TestAsync(); var stateMachine = task.GetType().GetField("<>m_stateMachine", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)?.GetValue(task); // 序列化该对象直接触发Error事件 JsonConvert.SerializeObject(stateMachine);
你之前给JsonConvert.DeserializeObject<Dictionary<string, string>>传null没有触发事件是正常的,因为null转字典是合法操作,本身不会抛出序列化异常。
调试定位建议
- 先完善错误日志的上下文信息,修改Error事件的逻辑,补充当前序列化对象类型、请求链路信息:
// 需先在Startup中注册services.AddHttpContextAccessor(); options.SerializerSettings.Error = (sender, args) => { var objectType = args.CurrentObject?.GetType().FullName ?? "null"; var requestPath = _httpContextAccessor.HttpContext?.Request.Path ?? "未知请求路径"; _logger.LogError(args.ErrorContext.Error, "序列化失败 请求路径:{Path} 序列化对象类型:{ObjectType} 错误路径:{ErrorPath}", requestPath, objectType, args.ErrorContext.Path); args.ErrorContext.Handled = true; };
- 测试环境下临时注释
args.ErrorContext.Handled = true;,让异常直接抛出,此时可以拿到完整的调用栈,直接定位触发序列化的具体接口和返回对象。 - 排查所有Controller接口的返回值,重点检查返回dynamic动态类型、Task、Delegate、反射类型(MethodInfo/Type等)的接口,这类接口很容易把内部生成的状态机对象、反射属性带到序列化流程中。
- 所有自定义返回类中,如果包含不需要序列化的非业务属性,统一加上
[JsonIgnore]标记。
内容的提问来源于stack exchange,提问作者Master
相关产品推荐
相关产品推荐

