当前位置: 首页 > news >正文

Newtonsoft.Json.JsonSerializationException

前言:

1 本文中内容全部手敲,如果存在错误,请在评论区指正

2 本文作学习探索使用,不涉及任何商业用途

3 本文会随着作者在软件开发过程中遇到问题,解决问题后不定期更新

一 自引用循环错误(self referencing loop)

1.1 错误原因

        对象之间存在循环引用(A 引用 B,B 又引用 A)

1.2 常见场景

1.2.1  异步任务状态机(AsyncTaskMethodBuilder

        ① 如何理解

                异步任务状态机是比较官方说法,你可以理解为异步任务(Task)返回的对象未完成就被调用序列化方法了。

        ② 真实原理

                一些编程语言,例如C# 会在编译(生成解决方案或者程序集的阶段)的时候生成一个状态机类(继承自IAsyncStateMachine),比如你的异步方法名称叫做 CreateFHDInput, 那么就会可能生成一个<CreateFHDInput>d__13 的类。其中d标识状态机类,13标识一个自增后缀,用于区分同名的多个生成类。 这个<CreateFHDInput>d__13 中有三个属性。

        I 当前的执行状态(_state)

        II 任务构造器(<>t_builder 类型为AsyncTaskMethodBuilder<T>)

        III 局部变量和上下文(_locals)

上面的变量之间相互引用,所以当你序列化一个未完成的任务返回对象时就会导致自引用循环错误

        ③ 错误复现

        下面的代码中CreateFHDInput是个异步方法 并返回一个对象

foreach (var item in input)
{ywy=await FindYWY(data1, item.YWY);var content =  CreateFHDInput(item, isCancel);string jsonContent = JsonConvert.SerializeObject(content);var res = await Request(jsonContent, Tools.RequestMethods.POST);await InsertAPIRecord(res, db, item.FHDH+item.FHHH.ToString("D3"), isCancel,Consts.LX_S);
}

在这个示例中,异步方法并没有使用await等待 任务执行完成,断点调试结果如下

因为未完成此任务,content对象仍然是一个状态机类的对象,状态是waitingforActivation等待任务结束。这是调用序列化方法就会导致循环引用报错。

        ④ 正确示例

        任务前加上await

foreach (var item in input)
{ywy=await FindYWY(data1, item.YWY);var content = await CreateFHDInput(item, isCancel);string jsonContent = JsonConvert.SerializeObject(content);var res = await Request(jsonContent, Tools.RequestMethods.POST);await InsertAPIRecord(res, db, item.FHDH+item.FHHH.ToString("D3"), isCancel,Consts.LX_S);
}

⑤: 解决方案

        I 使用await等待任务结束

        II 配置序列化设置忽略循环引用 (此方式我未验证)

// Newtonsoft.Json 配置
var settings = new JsonSerializerSettings {ReferenceLoopHandling = ReferenceLoopHandling.Ignore // 忽略循环引用
};
string json = JsonConvert.SerializeObject(yourObject, settings);// System.Text.Json 配置
var options = new JsonSerializerOptions {ReferenceHandler = ReferenceHandler.IgnoreCycles // .NET 6+ 支持
};
string json = JsonSerializer.Serialize(yourObject, options);

二 待更新

http://www.xdnf.cn/news/464419.html

相关文章:

  • 安卓A15系统实现修改锁屏界面默认壁纸功能
  • 多个docker-compose-xx 停止并完全卸载 删除
  • C++:字符数组与字符串指针变量的大小
  • 鸿蒙OSUniApp制作多选框与单选框组件#三方框架 #Uniapp
  • 协作赋能-1-制造业生产流程重构
  • Midjourney 最佳创作思路与实战技巧深度解析【附提示词与学习资料包下载】
  • 一些问题杂记
  • NY244NY249美光闪存颗粒NY252NY256
  • unity terrain 在生成草,树,石头等地形障碍的时候,无法触发碰撞导致人物穿过模型
  • 全链路压测实战指南:从理论到高可用架构的终极验证
  • Transformer的理解
  • Elasticsearch 分片机制高频面试题(含参考答案)
  • 【备忘踩坑】Android单元测试中读取测试assets的方法
  • 一套基于 Bootstrap 和 .NET Blazor 的开源企业级组件库
  • C#中Action的用法
  • Milvus Docker 部署教程
  • 【FFmpeg+SDL】使用FFmpeg捕获屏幕,SDL显示
  • 套路化编程:C# winform ListView 自定义排序
  • 5款AI驱动的MySQL数据库管理工具:提升运维效率的智能之选
  • 数智化招标采购系统如何实现分散评标?
  • Git/GitLab日常使用的命令指南来了!
  • Python——文件、异常、模块与包
  • 深入理解浏览器中的 window、document 和 window.parent
  • HarmonyOs开发之———UIAbility进阶
  • NVIDIA Omniverse 现已支持中文!
  • 问题处理——在ROS2(humble)+Gazebo+rqt下,无法显示仿真无人机的相机图像
  • 【LLIE专题】基于码本先验与生成式归一化流的低光照图像增强新方法
  • 【JS】vue3中组件命名问题
  • 世界模型+大模型+自动驾驶 论文小汇总
  • 测试--BUG(软件测试⽣命周期 bug的⽣命周期 与开发产⽣争执怎么办)