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

博客 分享
0 221
张三
张三 2022-01-26 17:54:34
悬赏:0 积分 收藏

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,但需要置顶Includethen参数,配置套娃查询……

继续!

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

答案肯定有啦

这就要用NewtonsoftJson了~

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

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

services.AddControllersWithViews()    .AddNewtonsoftJson(options => {        options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;    });

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

会导致套娃递归的属性直接变成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
程序设计实验室专注于互联网热门新技术探索与团队敏捷开发实践,在公众号「程序设计实验室」后台回复 linux、flutter、c#、netcore、android、kotlin、java、python 等可获取相关技术文章和资料,同时有任何问题都可以在公众号后台留言~
posted @ 2022-01-26 17:27 程序设计实验室 阅读(19) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员