当前位置:   article > 正文

Asp-Net-Core开发笔记:接口返回json对象出现套娃递归问题

net6 web api json套娃问题

前言

看了下推送记录,一个月前,OK,我又变成月更了o(╯□╰)o,这绝对不行![○・`Д´・ ○]

所以今天来更新了

其实不是我懒得更新或者是太忙,其实是最近在写一篇很长的博客,一直没写完( Ĭ ^ Ĭ )

另外快过年了,我领到了公众号作者的红包封面定制机会,接下来找时间设计(copy)一个好看的红包封面作为粉丝福利发给各位读者大大511e8804fdbd55a279d0353f9b74df39.png

好吧,先进入正题……

有一个关于WebApi序列化的问题,跟设计有关,但在涉及到关联字段的时候经常会遇到。

实体类

先看看实体类定义,限于篇幅,只保留几个关键字段。

  1. public class CrawlTask : EntityBase {
  2.     /// <summary>
  3.     /// 爬虫名称
  4.     /// </summary>
  5.     public string Name { get; set; }
  6.     /// <summary>
  7.     /// 创建这个爬虫的用户
  8.     /// </summary>
  9.     public User User { get; set; }
  10.     /// <summary>
  11.     /// 用户ID
  12.     /// </summary>
  13.     public string? UserId { get; set; }
  14. }

用户实体类:

  1. public class User : EntityBase {
  2.     /// <summary>
  3.     /// 用户名
  4.     /// </summary>
  5.     public string Name { get; set; }
  6.     /// <summary>
  7.     /// 用户创建的爬虫
  8.     /// </summary>
  9.     public List<CrawlTask> CrawlTasks { get; set; }
  10. }

接口

然后接口这样写:

  1. /// <summary>
  2. /// 获取用户创建的全部爬虫
  3. /// </summary>
  4. /// <returns></returns>
  5. [HttpGet]
  6. public ActionResult<List<CrawlTask>> GetAll() {
  7.     var user = _authService.GetUser(User.Identity?.Name);
  8.     return user.CrawlTasks;
  9. }

然后请求这个接口,我们期望的数据是:

  1. [
  2.   {
  3.     "name""爬虫名称",
  4.     "user": {
  5.      "name""用户名"
  6.     },
  7.     "userId""0f3d4b2f-3b4e-4d08-8f4c-0009a316f041",
  8.     "id""4d52d83b-f3ec-47c6-ab26-e241c09c14d1"
  9.   }
  10. ]

报错

但事实是直接报错:

  1. 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.
  2. 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数据是:

  1. {
  2.     "name""test crawl123",
  3.     "user": {
  4.         "name""string"
  5.     },
  6.     "userId""0f3d4b2f-3b4e-4d08-8f4c-0009a316f041",
  7.     "id""4d52d83b-f3ec-47c6-ab26-e241c09c14d1"
  8. }

Crawl对象下的User只有Name属性,不要把CrawlTasks列表也显示出来,但程序它不知道啊,User里有CrawlTasks,然后CrawlTasks里面又有User,这就陷入一个套娃递归了……

初步解决

很明显,这根设计和数据获取方式有问题,可以通过换个查询方式来避免,比如:

  1. [HttpGet]
  2. public ActionResult<List<CrawlTask>> GetAll() {
  3.     return _crawlRepo
  4.         .Where(a => a.UserId == User.Identity.Name)
  5.         .ToList();
  6. }

因为这里没有请求Crawl的导航属性User,所以不会读取User对象的信息,出现的结果是这样:

  1. [
  2.   {
  3.     "name""test crawl123",
  4.     "user": null,
  5.     "userId""0f3d4b2f-3b4e-4d08-8f4c-0009a316f041",
  6.     "id""4d52d83b-f3ec-47c6-ab26-e241c09c14d1"
  7.   }
  8. ]

可以看到User对象的值是null,对于接口来说已经够用了,毕竟这是获取当前用户的所有爬虫,所有爬虫的user属性都是同一个,没必要重复啦。

不过即使把User对象加上也是完全没问题的,这里改一下接口看一下效果:

  1. [HttpGet]
  2. public ActionResult<List<CrawlTask>> GetAll() {
  3.     return _crawlRepo.Select
  4.         .Where(a => a.UserId == User.Identity.Name)
  5.         .Include(a => a.User)  // 添加了这行代码,请求关联对象
  6.         .ToList();
  7. }

返回的结果:

  1. [
  2.   {
  3.     "name""test crawl123",
  4.     "user": {
  5.       "name""string",
  6.       "crawlTasks": null,
  7.       "id""0f3d4b2f-3b4e-4d08-8f4c-0009a316f041"
  8.     },
  9.     "userId""0f3d4b2f-3b4e-4d08-8f4c-0009a316f041",
  10.     "id""4d52d83b-f3ec-47c6-ab26-e241c09c14d1"
  11.   }
  12. ]

可以看到,返回的Crawl对象中,User对象里的crawlTasks属性是空的,因为我们前面加的那行代码:.Include(a => a.User),FreeSQL还支持进一步查询User的导航属性crawlTasks,但需要置顶Includethen参数,配置套娃查询……

继续!

那有没有什么办法是不改动接口代码的情况下,解决接口套娃的问题?

答案肯定有啦

这就要用NewtonsoftJson了~

首先安装Microsoft.AspNetCore.Mvc.NewtonsoftJson这个nuget

然后在服务配置里面添加代码

  1. services.AddControllersWithViews()
  2.     .AddNewtonsoftJson(options => {
  3.         options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
  4.     });

然后再请求接口,返回的结果就跟上面的一样啦~

会导致套娃递归的属性直接变成null~

PS:这个代码的作用就是把WebApi默认的json序列化器从System.Text.Json改成NewtonsoftJson,并且配置处理套娃递归的方式为忽略~

参考文档

  • https://stackoverflow.com/questions/59199593/net-core-3-0-possible-object-cycle-was-detected-which-is-not-supported

5e98305cfeb0fd59ef299c1c4deac197.png

代码使我头疼之React初学习


aa9dee731325238ee5962f88a29c7327.png

AspNetCore在docker部署时遇到一个小坑


449ff204d231e951659db888c101f958.png

Asp.Net Core部署:早知道,还是docker!以及一点碎碎念


e08f4f242839d0a8e358c5c59a1bd305.png

纯前端实现词云展示+附微博热搜词云Demo代码


8c5f012e67c333751294cff087b6bf2d.png

一个玄学的爬虫bug竟让我放弃Python语言!?背后的原因令人唏嘘~


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/550336
推荐阅读
相关标签
  

闽ICP备14008679号