【问题标题】:.net core : incomplete JSON response.net 核心:不完整的 JSON 响应
【发布时间】: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; }
}

我真的不明白发生了什么,如果你有任何想法

【问题讨论】:

标签: c# asp.net-core .net-core asp.net-core-mvc


【解决方案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; }
    }

然后您将您的用户 UserSport 模型映射到您的 UserDtoSportDto 进行此映射的一个好工具是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 方法。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-06-30
            • 1970-01-01
            • 1970-01-01
            • 2018-02-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多