.NET5 System.Text.Json检测到对象循环抛出JsonException问题咨询
问题根源
该异常抛出在控制器逻辑执行完成后的响应序列化阶段,不在业务代码的try-catch覆盖范围内因此无法被捕获。System.Text.Json默认开启对象循环检测,发现你返回的Person和Schema存在互相引用的循环结构时直接抛出异常,返回的500错误响应缺失标准CORS头,才会被调用端误判为CORS策略问题。
解决方案
方案1:使用DTO切断循环(推荐)
不要直接将业务实体/数据库实体作为接口返回值,单独定义接口专用的DTO(数据传输对象),按需保留字段,移除会导致循环的导航属性即可:
// 接口返回专用的Person DTO public class PersonDto { public string Name { get; set; } // 不需要返回关联的Schema列表时直接删除该属性,从根源切断循环 }
该方案无额外序列化开销,也不会暴露不必要的业务字段,符合接口设计规范。
方案2:全局配置序列化规则处理循环
如果暂时不想调整实体结构,可以直接修改System.Text.Json的全局配置:
.NET 6及以上版本,在Program.cs中添加配置:
builder.Services.AddControllers() .AddJsonOptions(options => { // 检测到循环引用时将对应字段序列化为null options.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles; // 如果需要保留引用关系支持反序列化恢复循环结构,可替换为如下配置 // options.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.Preserve; });
.NET Core 3.1/.NET 5版本
低版本System.Text.Json原生不支持循环引用处理,可替换为Newtonsoft.Json(Json.NET)作为序列化器:
- 安装NuGet包:
Microsoft.AspNetCore.Mvc.NewtonsoftJson - 在Program.cs/Startup.cs中添加配置:
services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; });
方案3:为循环属性添加忽略序列化特性
如果仅需要在特定场景下忽略某一个导航属性,可直接在属性上加[JsonIgnore]特性,注意要和你使用的序列化器对应:
- 使用System.Text.Json:引用命名空间
System.Text.Json.Serialization下的JsonIgnore - 使用Newtonsoft.Json:引用命名空间
Newtonsoft.Json下的JsonIgnore
public class Person { public string Name { get; set; } [JsonIgnore] // 序列化时自动忽略该属性,切断循环 public List<Schema> Schemas { get; set; } } public class Schema { // 也可选择在Schema的Persons属性上加特性,按需选择即可 public List<Person> Persons { get; set; } }
内容的提问来源于stack exchange,提问作者Antfolkarn
相关产品推荐
相关产品推荐

