Asp-Net-Core开发笔记:接口返回json对象出现套娃递归问题
前言#
看了下推送记录,一个月前,OK,我又变成月更了o(╯□╰)o,这绝对不行![○・`Д´・ ○]
所以今天来更新了
其实不是我懒得更新或者是太忙,其实是最近在写一篇很长的博客,一直没写完( Ĭ ^ Ĭ )
好吧,先进入正题……
有一个关于WebApi序列化的问题,跟设计有关,但在涉及到关联字段的时候经常会遇到。
实体类#
先看看实体类定义,限于篇幅,只保留几个关键字段。
public class CrawlTask : EntityBase {
/// <summary>
/// 爬虫名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 创建这个爬虫的用户
/// </summary>
public User User { get; set; }
/// <summary>
/// 用户ID
/// </summary>
public string? UserId { get; set; }
}
用户实体类:
public class User : EntityBase {
/// <summary>
/// 用户名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 用户创建的爬虫
/// </summary>
public List<CrawlTask> CrawlTasks { get; set; }
}
接口#
然后接口这样写:
/// <summary>
/// 获取用户创建的全部爬虫
/// </summary>
/// <returns></returns>
[HttpGet]
public ActionResult<List<CrawlTask>> GetAll() {
var user = _authService.GetUser(User.Identity?.Name);
return user.CrawlTasks;
}
然后请求这个接口,我们期望的数据是:
[
{
"name": "爬虫名称",
"user": {
"name": "用户名"
},
"userId": "0f3d4b2f-3b4e-4d08-8f4c-0009a316f041",
"id": "4d52d83b-f3ec-47c6-ab26-e241c09c14d1"
}
]
报错#
但事实是直接报错:
System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles.
Path: $.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.User.CrawlTasks.Name.
很明显,返回的对象套娃递归了。
注意那个Path:$.User.CrawlTasks.User.CrawlTasks.User.Crawl...
,我们上面期望的json数据是:
{
"name": "test crawl123",
"user": {
"name": "string"
},
"userId": "0f3d4b2f-3b4e-4d08-8f4c-0009a316f041",
"id": "4d52d83b-f3ec-47c6-ab26-e241c09c14d1"
}
即Crawl
对象下的User
只有Name
属性,不要把CrawlTasks
列表也显示出来,但程序它不知道啊,User
里有CrawlTasks
,然后CrawlTasks
里面又有User
,这就陷入一个套娃递归了……
初步解决#
很明显,这根设计和数据获取方式有问题,可以通过换个查询方式来避免,比如:
[HttpGet]
public ActionResult<List<CrawlTask>> GetAll() {
return _crawlRepo
.Where(a => a.UserId == User.Identity.Name)
.ToList();
}
因为这里没有请求Crawl
的导航属性User
,所以不会读取User
对象的信息,出现的结果是这样:
[
{
"name": "test crawl123",
"user": null,
"userId": "0f3d4b2f-3b4e-4d08-8f4c-0009a316f041",
"id": "4d52d83b-f3ec-47c6-ab26-e241c09c14d1"
}
]
可以看到User
对象的值是null,对于接口来说已经够用了,毕竟这是获取当前用户的所有爬虫,所有爬虫的user属性都是同一个,没必要重复啦。
不过即使把User
对象加上也是完全没问题的,这里改一下接口看一下效果:
[HttpGet]
public ActionResult<List<CrawlTask>> GetAll() {
return _crawlRepo.Select
.Where(a => a.UserId == User.Identity.Name)
.Include(a => a.User) // 添加了这行代码,请求关联对象
.ToList();
}
返回的结果:
[
{
"name": "test crawl123",
"user": {
"name": "string",
"crawlTasks": null,
"id": "0f3d4b2f-3b4e-4d08-8f4c-0009a316f041"
},
"userId": "0f3d4b2f-3b4e-4d08-8f4c-0009a316f041",
"id": "4d52d83b-f3ec-47c6-ab26-e241c09c14d1"
}
]
可以看到,返回的Crawl
对象中,User
对象里的crawlTasks
属性是空的,因为我们前面加的那行代码:.Include(a => a.User)
,FreeSQL还支持进一步查询User
的导航属性crawlTasks
,但需要置顶Include
的then
参数,配置套娃查询……
继续!#
那有没有什么办法是不改动接口代码的情况下,解决接口套娃的问题?
答案肯定有啦
这就要用NewtonsoftJson
了~
首先安装Microsoft.AspNetCore.Mvc.NewtonsoftJson
这个nuget包
然后在服务配置里面添加代码
services.AddControllersWithViews()
.AddNewtonsoftJson(options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
然后再请求接口,返回的结果就跟上面的一样啦~
会导致套娃递归的属性直接变成null~
PS:这个代码的作用就是把WebApi默认的json序列化器从System.Text.Json
改成NewtonsoftJson
,并且配置处理套娃递归的方式为忽略~
参考文档#
作者:DealiAxy
出处:https://www.cnblogs.com/deali/p/15847475.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
微信公众号:「程序设计实验室」
新版StarBlog已经上线,地址:http://blog.deali.cn
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· 2分钟学会 DeepSeek API,竟然比官方更好用!
· .NET 使用 DeepSeek R1 开发智能 AI 客户端
· DeepSeek本地性能调优
· 一文掌握DeepSeek本地部署+Page Assist浏览器插件+C#接口调用+局域网访问!全攻略
2021-01-26 Django数据导入导出神器django-import-export使用
2021-01-26 我的2020回顾——技术篇
2021-01-26 Selenium爬虫实战:截取网页上的图片