【问题标题】:Seralization issue in WebApi 2.0Web Api 2.0 中的序列化问题
【发布时间】:2014-08-18 21:23:05
【问题描述】:

我正在使用 EF 6.0 Code First、AutoMapper 和 WebApi 2.0 开发 REST API。

我正在努力序列化数据,或者更具体地说;选择响应请求时应序列化的内容。

假设我正在为具有以下课程的足球联赛创建一个应用程序:

public class Player
{
    public String Name { get; set; }
    public virtual ICollection<Team> Teams { get; set; } // example
}

public class Team
{
    public String Name { get; set; }
    public virtual ICollection<Team> Players { get; set; }
    public virtual ICollection<FootballGame> Games { get; set; }
}

public class FootballGame
{
    public Team Team1 { get; set; }
    public Team Team2 { get; set; }
    public DateTime DateTime { get; set; }
}

我有一个名为 PlayersController 的 API 控制器,以及一个应该返回该播放器的普通 Get 方法 url/api/players/id。

但是,由于 LazyLoading、序列化和多对多关系,我返回了与该播放器相关的每个对象:

{
  "$id": "1",
  "Id": 1,
  "Name": "Jon Jones",
  "Teams": [
    {
      "$id": "2",
      "Id": 1,
      "Name": "Liverpool",
      "Players": [
        {
          "$id": "3",
          "Id": 2,
          "Name": "James White",
          "Teams": [
            {
              "$ref": "2"
            },
            {
              "$id": "4",
              "Id": 2,
              "Name": "Man Utd",
              "Players": [
                {
                  "$ref": "3"
                },
                {
                  "$id": "5",
                  "Id": 3,
                  "Name": "John Snow",
                  "Teams": [
                    {
                      "$ref": "2"
                    },
                    {
                      "$ref": "4"
                    }
                  ]
                },
                {
                  "$ref": "1"
                }
              ],
              "Games": [
                {
                  "$id": "6",
                  "Id": 1,
                  "Team1": {
                    "$ref": "2"
                  },
                  "Team2": {
                    "$ref": "4"
                  },
                  "DateTime": "2014-08-18T23:20:01.7797942+02:00"
                },
                {
                  "$id": "7",
                  "Id": 2,
                  "Team1": {
                    "$id": "8",
                    "Id": 3,
                    "Name": "Man City",
                    "Players": [
                      {
                        "$ref": "1"
                      },
                      {
                        "$ref": "3"
                      },
                      {
                        "$id": "9",
                        "Id": 4,
                        "Name": "Elton John",
                        "Teams": [
                          {
                            "$ref": "2"
                          },
                          {
                            "$ref": "8"
                          }
                        ]
                      }
                    ],
                    "Games": [
                      {
                        "$ref": "7"
                      },
                      {
                        "$id": "10",
                        "Id": 5,
                        "Team1": {
                          "$ref": "2"
                        },
                        "Team2": {
                          "$ref": "8"
                        },
                        "DateTime": "2014-08-18T23:20:01.7807943+02:00"
                      }
                    ]
                  },
                  "Team2": {
                    "$ref": "4"
                  },
                  "DateTime": "2014-08-18T23:20:01.7807943+02:00"
                }
              ]
            },
            {
              "$ref": "8"
            }
          ]
        },
        {
          "$ref": "5"
        },
        {
          "$ref": "9"
        }
      ],
      "Games": [
        {
          "$ref": "6"
        },
        {
          "$ref": "10"
        }
      ]
    },
    {
      "$ref": "4"
    }
  ]
}

我怎样才能以一种简单的方式选择只返回球员,而对于球队,而不是返回球队可以获得数据的网址,例如:

{
  "Id": 1,
  "Name": "Jon Jones",
  "Teams": "http://url/api/player/1/teams/"
}

编辑: 通过按照建议禁用延迟加载,我得到:

{
  "Id": 1,
  "Name": "Jon Jones",
  "Teams": []
}

如果这是要走的路,是否有“最佳实践”来添加 uri 以让团队进入那里?

【问题讨论】:

标签: c# rest json.net asp.net-web-api asp.net-web-api2


【解决方案1】:

您应该在构建 Web 服务时禁用延迟加载 - 最好强制自己明确要获取哪些数据。另一种方法是在您不希望序列化程序查看的类的属性上删除 [JsonIgnore] 属性。

【讨论】:

    【解决方案2】:

    正如 Robert Levy 建议的那样,您应该禁用延迟加载。或者,除了实体之外,您还应该定义 DTO(数据传输对象)。这些只是不属于实体框架的普通对象。它们的目的是让您定义一个看起来与您的数据库不同的外部 API。因此,您将查询您的实体并编写一些代码来将您的 POCO 的内容映射到您的 DTO。

    如果您正在做一些非常简单的事情,这可能看起来有点矫枉过正(因为您的 DTO 可能看起来与您的实体框架对象一模一样。

    不过,对于任何重要的事情,将数据库设计与 API 的拓扑解耦会很有用。

    【讨论】:

      猜你喜欢
      • 2012-02-19
      • 2015-02-07
      • 2016-12-11
      • 2018-04-23
      • 2016-06-22
      • 2020-09-18
      • 1970-01-01
      • 1970-01-01
      • 2012-03-19
      相关资源
      最近更新 更多