包含或不包含资源子项的RESTful方式?

时间:2014-03-11 17:07:00

标签: api rest nested

假设我有一个team对象,它有name属性,city属性和players属性,其中players属性是一系列可能很多的球员。这在具有teams表和players表的SQL数据库中表示,其中每个玩家都有nameteam_id

基于这个简单的数据结构构建一个RESTful api,如果返回对象应该/可以包含一个播放器列表,在点击/teams/:id时,我是否有明确的规则存在疑问?

我有一个观点,那就是需要向一个团队及其玩家展示他们的名字,所以:

1:/teams/:id是否应该加入场景后面的两个表并返回完整的team对象,其中包含一个名字和id的数组?

2:/teams/:id是否应该加入场景后面的两个表并返回team对象,其中包含一个属性,这是一个只有id的数组,然后必须是一个接一个地询问/players/:id

3:是否应该拨打两个电话,一个拨打/teams/:id,一个拨打/teams/:id/players

4:是否应该像/teams/:id?fields=name,city,players一样使用查询字符串?

如果要做的是2或3,那么如何处理这种情况,团队中也可能有多个城市,导致数据库中的另一个cities表保持标准化?是否应在/teams/:id/cities创建新端点。

创建RESTful API时,数据库中的规范化数据结构是否规定了API中的端点?

2 个答案:

答案 0 :(得分:7)

通常使用RESTful API,最好是用例指示API的端点,而不一定是数据结构。

如果你有时只需要团队,有时候只需要一个团队的参与者,有时候需要两个团队,我会有3个不同的电话,可能是/teams/:id/players/:teamid和{{ 1}}(或类似的东西)。

您希望以这种方式执行此操作的原因是因为它最大限度地减少了需要为任何给定页面进行的HTTP请求的数量。在所有典型的性能问题中,HTTP请求数量的增加通常是最常见的性能命中之一,通常是最容易避免的一种。

话虽这么说,你也不想疯狂,以至于你创造了一个过度膨胀的API。仔细考虑典型的用例并对其进行调用。不要仅仅为了它而实现你能想到的每一种可能的组合。请记住You Aren't Gonna Need It

答案 1 :(得分:3)

我建议像:

GET /teams
{
    "id" : 12,
    "name" : "MyTeam"
    "players" :
    {
        "self" : "http://my.server/players?teamName=MyTeam"
    },
    "city" :
    {
        "self" : "http://my.server/cities/MyCity"
    }
}

GET /cities
GET /cities/{cityId}
GET /players
GET /players/{playerId}

然后,您可以使用URI来调用以获取所需的任何其他相关资源。如果您希望灵活地嵌入值,可以使用?expand,例如:

GET /teams?expand=players
{
    "id" : 12,
    "name" : "MyTeam"
    "players" :
    {
        "self" : "http://my.server/players?teamName=MyTeam",
        [
            {
                 "name" : "Mary",
                 "number" : "12"
            },
            {
                 "name" : "Sally",
                 "number" : "15"
            }
         ]
    },
    "city" :
    {
        "self" : "http://my.server/cities/MyCity"
    }
}