当前位置:首页 > C# > 正文

C#中JSON序列化的循环引用问题详解(小白也能轻松掌握循环引用处理技巧)

在使用 C# 进行开发时,我们经常需要将对象转换为 JSON 格式进行传输或存储。然而,当对象之间存在循环引用(Circular Reference)时,JSON 序列化器可能会抛出异常或陷入无限递归。本文将手把手教你如何在 C# 中优雅地处理 JSON 序列化中的循环引用问题,无论你是新手还是有经验的开发者都能轻松掌握。

C#中JSON序列化的循环引用问题详解(小白也能轻松掌握循环引用处理技巧) C# JSON序列化 循环引用处理 System.Text.Json Newtonsoft.Json 第1张

什么是循环引用?

循环引用是指两个或多个对象相互引用,形成一个闭环。例如:

  • 一个 Parent 对象包含一个 Child 对象;
  • 而这个 Child 对象又持有一个指向其 Parent 的引用。

在这种情况下,如果直接对 Parent 进行 JSON 序列化,序列化器会不断尝试序列化 Parent → Child → Parent → Child...,最终导致栈溢出或抛出异常。

C# 中常用的 JSON 序列化库

目前 C# 开发中最常用的两个 JSON 序列化库是:

  1. System.Text.Json:.NET Core 3.0+ 内置的高性能 JSON 库;
  2. Newtonsoft.Json(也称 Json.NET):功能强大、社区广泛使用的第三方库。

下面我们将分别介绍这两个库如何处理循环引用。

方法一:使用 System.Text.Json 处理循环引用

从 .NET 5 开始,System.Text.Json 原生支持通过配置来忽略循环引用。你只需设置 ReferenceHandler 选项即可。

using System.Text.Json;using System.Text.Json.Serialization;// 定义模型类public class Parent{    public string Name { get; set; }    public Child Child { get; set; }}public class Child{    public string Name { get; set; }    public Parent Parent { get; set; }}// 使用示例class Program{    static void Main()    {        var parent = new Parent { Name = "张三" };        var child = new Child { Name = "小明", Parent = parent };        parent.Child = child;        var options = new JsonSerializerOptions        {            ReferenceHandler = ReferenceHandler.IgnoreCycles,            WriteIndented = true        };        string json = JsonSerializer.Serialize(parent, options);        Console.WriteLine(json);    }}

输出结果将自动忽略造成循环的部分,避免无限递归。注意:ReferenceHandler.IgnoreCycles 是 .NET 7 引入的功能,在 .NET 5/6 中需使用 ReferenceHandler.Preserve 并配合反序列化,但更推荐升级到 .NET 7+ 以获得最佳体验。

方法二:使用 Newtonsoft.Json 处理循环引用

如果你仍在使用 Newtonsoft.Json,它提供了更灵活的选项来处理循环引用。

using Newtonsoft.Json;// 在类上添加特性public class Parent{    public string Name { get; set; }    public Child Child { get; set; }}public class Child{    public string Name { get; set; }    [JsonIgnore] // 忽略该属性,防止循环    public Parent Parent { get; set; }}// 或者在序列化时全局配置class Program{    static void Main()    {        var parent = new Parent { Name = "李四" };        var child = new Child { Name = "小红", Parent = parent };        parent.Child = child;        string json = JsonConvert.SerializeObject(            parent,            Formatting.Indented,            new JsonSerializerSettings            {                ReferenceLoopHandling = ReferenceLoopHandling.Ignore            });        Console.WriteLine(json);    }}

这里展示了两种方式:

  • 使用 [JsonIgnore] 特性忽略特定属性;
  • 通过 JsonSerializerSettings 全局设置 ReferenceLoopHandling.Ignore 自动跳过循环引用。

如何选择?

- 如果你使用的是 .NET 7 或更高版本,推荐优先使用 System.Text.Json,性能更好且是官方维护;

- 如果项目依赖旧版 .NET 或需要更复杂的序列化控制(如自定义转换器),Newtonsoft.Json 依然是可靠的选择。

总结

处理 C# JSON 序列化中的循环引用并不难。关键在于理解你的对象结构,并根据所用的 JSON 库(System.Text.JsonNewtonsoft.Json)选择合适的策略。无论是通过配置选项还是添加特性,都能有效避免程序崩溃,确保数据正确传输。

希望这篇教程能帮助你彻底掌握 C# JSON序列化 中的 循环引用处理 技巧!