.net 核心:不完整的 JSON 响应
Posted
技术标签:
【中文标题】.net 核心:不完整的 JSON 响应【英文标题】:.net core : incomplete JSON response 【发布时间】:2017-11-21 18:11:14 【问题描述】:我正在尝试构建用于训练的简单 API,在我的数据库中我有用户(名字、姓氏、电子邮件密码、list<sports>
)和运动(姓名、用户 ID)。
当我想获得我的用户时,一切都很好,我得到了一个充满运动的对象。但是 JSON 响应是不完整的,它在中间被“剪切”了。
["firstName":"Nicolas","lastName":"Bouhours","email":"n.bouh@test.com","password":"nico@hotmail.fr","sports":["name":"Trail","userId":1
这是我的控制器:
// GET: api/Users
[HttpGet]
public IEnumerable<User> GetUsers()
var users = _context.Users.Include(u => u.Sports).ToList();
return users;
还有我的模型:
public class Sport : BaseEntity
public string Name get; set;
public int UserId get; set;
public User User get; set;
public class User : BaseEntity
public String FirstName get; set;
public String LastName get; set;
public String Email get; set;
public String Password get; set;
public List<Sport> Sports get; set;
public class SportAppContext : DbContext
public SportAppContext(DbContextOptions<SportAppContext> options) : base(options)
public DbSet<User> Users get; set;
public DbSet<Sport> Sports get; set;
我真的不明白发生了什么,如果你有任何想法
【问题讨论】:
试试这个:***.com/a/39024972/93345 【参考方案1】:我现在遇到了同样的问题。您还可以更改 JSON 序列化/配置设置以忽略自引用循环,如接受的答案 for this question
所示public void ConfigureServices(IServiceCollection services)
services.AddMvc().AddJsonOptions(options =>
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
);
【讨论】:
在我的情况下,添加映射和视图模型可以解决循环 非常好的和干净的解决方案来解决不完整的 json 问题。 (Y)【参考方案2】:我在我的一个项目中遇到了这个问题。这是由自引用循环引起的。
您需要创建某种 DTO(数据传输对象),用于生成您的 JSON。
在您的 DTO 中,您删除了反向关系,因此您最终会得到类似的东西
public class SportDto
public string Name get; set;
public class UserDto
public String FirstName get; set;
public String LastName get; set;
public String Email get; set;
public String Password get; set;
public List<SportDto> Sports get; set;
然后您将您的用户 User
和 Sport
模型映射到您的 UserDto
和 SportDto
进行此映射的一个好工具是AutoMapper。您可以阅读文档以了解如何开始。
映射完成后,您将 DTO 作为 JSON 而不是 模型 发送。
【讨论】:
【参考方案3】:只是添加另一个可能发生这种情况的独特场景。如果您的 DAL 返回可查询对象,也会发生这种情况。在我的场景中,我从 DAL 返回了一个装箱的对象,并且有类似这样的 linq 查询
...
RootLevelProp1 = "asd",
RootLevelProp2 = "asd",
Trades = b.Trades.OrderBy(c => c.Time).Select(c => new
c.Direction,
c.Price,
c.ShareCount,
c.Time
) //<---- This was being returned as a queryable to the controller
Trades
查询从未被执行,即使它的根对象调用了 .ToListAsync()
。发生的事情是控制器将返回结果,但只返回 Trades
部分,并且 Json 不会正确终止。然后我意识到在我编写的一些自定义中间件中捕获了一个异常,它抱怨数据读取器已经打开。在没有深入调查的情况下,我认为它必须对 DI 以及它如何处理上下文的生命周期做一些事情。解决方法是在交易中添加ToList
。这是一种从 DAL 传递数据的丑陋方式,但这只是一个有趣的项目。
【讨论】:
【参考方案4】:就我而言,这通过使用 Newtonsoft 解决了我在核心 3 上的问题: https://docs.microsoft.com/en-us/aspnet/core/web-api/advanced/formatting?view=aspnetcore-3.0#add-newtonsoftjson-based-json-format-support
在 ASP.NET Core 3.0 之前,默认使用 JSON 格式化程序 使用 Newtonsoft.Json 包实现。在 ASP.NET Core 3.0 或 稍后,默认的 JSON 格式化程序基于 System.Text.Json。 支持基于 Newtonsoft.Json 的格式化程序和功能 通过安装 Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet 打包并在 Startup.ConfigureServices 中进行配置。
public void ConfigureServices(IServiceCollection services)
services.AddControllers()
.AddNewtonsoftJson();
【讨论】:
【参考方案5】:在我的情况下,所选答案也是正确的,我的 JSON 响应被我的 JSON 响应中的引用循环截断,设置 ReferenceLoopHandling.Ignore 确实解决了我的问题。但是,在我看来,这不是最好的解决方案,因为这会维护模型中的循环引用。更好的解决方案是在模型中使用 [JsonIgnore] 属性。
您的模型中存在问题:
public class Sport : BaseEntity
public string Name get; set;
public int UserId get; set;
public User User get; set; //This is the cause of your circular reference
public class User : BaseEntity
public String FirstName get; set;
public String LastName get; set;
public String Email get; set;
public String Password get; set;
public List<Sport> Sports get; set;
如您所见,您的用户导航属性是此响应被截断的位置。具体来说,它将导致 json 响应中的每个 Sport 包含响应中每个运动条目的所有用户信息。 Newtonsoft 不喜欢这样。解决方案是简单地 [JsonIngore] 导致此循环引用的导航属性。在您的代码中,这将是:
public class Sport : BaseEntity
public string Name get; set;
public int UserId get; set;
[JsonIgnore]
public User User get; set; //fixed
public class User : BaseEntity
public String FirstName get; set;
public String LastName get; set;
public String Email get; set;
public String Password get; set;
public List<Sport> Sports get; set;
【讨论】:
【参考方案6】:面临类似问题,响应被截断。问题是尝试格式化日期的 getter 方法。
【讨论】:
以上是关于.net 核心:不完整的 JSON 响应的主要内容,如果未能解决你的问题,请参考以下文章
DS.RESTAdapter 的预期 JSON 响应的完整列表是啥?
如何使用服务器的 JSON 响应对象(而不是完整对象)中的属性来填充 Kendo 网格?