【问题标题】:Collection Navigation Properties returning odd JSON hierarchy返回奇数 JSON 层次结构的集合导航属性
【发布时间】:2018-10-04 01:28:52
【问题描述】:

我有 2 节课:

    public class A
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public B myB { get; set; }
    }

    public class B
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public ICollection<A> myAs { get; set; }
    }

我正在使用 Postman 来测试 Api 调用。

    public IEnumerable<B> GetBs()
    {
       return _context.Bs.Include(b => b.myAs).ToList();
    }

按预期返回 B 对象及其关联的 A 对象的列表:

{
        "Id": 1,
        "Name": "B2",
        "myAs": [
            {
                "Id": 1,
                "Name": "A1"
            },
            {
                "Id": 2,
                "Name": "A2"
            }
        ]
    },
    {
        "Id": 2,
        "Name": "B3",
        "myAs": [
            {
                "Id": 3,
                "Name": "A3"
            },
            {
                "Id": 4,
                "Name": "A4"
            },
            {
                "Id": 5,
                "Name": "A5"
            }
        ]
    }

然而,反过来会返回一个奇怪的层次结构:

    public IEnumerable<A> GetAs()
    {
        return _context.As.Include(a => a.myB).ToList();
    }

返回:

[
{
        "Id": 1,
        "Name": "A1",
        "myB": {
            "Id": 1,
            "Name": "B2",
            "myAs": [
                {
                    "Id": 2,
                    "Name": "A2"
                }
            ]
        }
    },
    {
        "Id": 2,
        "Name": "A2",
        "myB": {
            "Id": 1,
            "Name": "B2",
            "myAs": [
                {
                    "Id": 1,
                    "Name": "A1"
                }
            ]
        }
    },
    {
        "Id": 3,
        "Name": "A3",
        "myB": {
            "Id": 2,
            "Name": "B3",
            "myAs": [
                {
                    "Id": 4,
                    "Name": "A4"
                },
                {
                    "Id": 5,
                    "Name": "A5"
                }
            ]
        }
    }
]

GetAs 方法返回 A 对象和 B 对象以及进一步嵌套的 A 对象。

经过一番研究后我的理解(我在这里可能非常错误)是因为 A 对 B (myB) 具有导航属性,而 B 对 A 对象列表 (myAs) 具有导航属性,这会导致一些一种循环。

我的问题是

  1. 我的理解正确吗?这就是层次结构以这种奇怪的布局返回的原因吗?
  2. 我该如何解决这个问题?我可以将 ICollection 导航属性从域模型中取出,但我无法再查询 As 及其关联的 B?

注意 A 和 B 实际上不是我的域模型。我只是想让示例尽可能简单。

提前致谢。

【问题讨论】:

  • 第二个 JSON 样本格式不正确。如果我将它上传到jsonlint.com 我会收到一个错误Error: Parse error on line 12: Expecting 'EOF', got ',' 基本上它看起来像是一系列连接在一起的独立 JSON 文件。
  • 嗨,是的,我错过了开头和结尾的方括号。它现在验证。关于层次结构布局的任何想法?我完全不知道该做什么

标签: c# json.net postman navigation-properties


【解决方案1】:

这里有几件事:

输出具有预期的形状。正如您所怀疑的,串行器正在扩展双向引用。想想如果你手动递归地序列化每个对象的每个属性会发生什么。这就是正在发生的事情。

要解决眼前的问题,请配置您的默认序列化程序设置,如下所示:

jsonFormatter.SerializerSettings.ReferenceLoopHandling  = Newtonsoft.Json.Serialization.ReferenceLoopHandling.Ignore;

上述方法在原型设计时很有用,但当您的应用程序更加正式时,您应该从您的 Web API 端点创建并返回专用视图模型类型。

public class AViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class BViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public IEnumerable<AViewModel> myAs { get; set; }
}

public IEnumerable<BViewModel> GetBs()
{
   return _context.Bs.Include(b => b.myAs)
        .Select(b => new BViewModel
        {
            Id = b.Id,
            Name = b.Name,
            As = b.As.Select(a => new AViewModel
            {
                 Id = a.Id,
                 Name = a.Name
            })
        })
        .ToList();
}

值得注意的是,有一些库,例如广受好评的 AutoMapper,可以为您执行模型类型之间的这些转换,使用反射自动按名称分配相应的属性。

就我个人而言,我尽量避免使用基于反射的方法,因为它们往往会使代码难以静态推理。这既阻碍了我们这样的人类读者,也阻碍了 C# 语言等工具。

也就是说,根据手头的任务进行权衡是值得的。我希望最终能看到语言级别的支持,它可以消除这种样板分配,而不会进入严格的领域,但我还有很长的时间要等待。

【讨论】:

  • 您好,感谢您的回复。我已经添加了上述 JSON 设置。这使我可以查看返回的 JSON,而不会出现“自引用循环”错误。至于您的专用视图模型建议,您可以通过任何方式提供有关其工作原理的示例。我还是没有运气
  • 优秀。非常感谢你的帮助。非常感谢。
  • 我一定会去看看的。非常感谢
  • 当然。我更新了一些关于此类工具缺陷的评论。祝你好运。
  • 如何完成相反的操作(GetAs)。我希望能够完成这两种操作(GetAs 和 GetBs),但如果不更改我的模型(例如删除集合导航)就看不到如何操作。来自 B 的属性并添加导航。属性返回 A
猜你喜欢
  • 1970-01-01
  • 2016-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多