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

acr*_*uui 9 api rest nested

假设我有一个team对象,它有一个name属性,一个city属性和一个players属性,其中players属性可能是许多玩家的数组.这在带有teams表和players表的SQL数据库中表示,其中每个玩家都有a name和a team_id.

基于这个简单的数据结构构建一个RESTful api,如果有一个明确的规则,我是否有疑问,如果返回对象应该/可以包含一个玩家列表,何时命中/teams/:id

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

1:应该/teams/:id加入场景后面的两个表并返回完整的team对象,带有一个player属性,这是一个名字和id的数组?

2:应该/teams/:id加入场景后面的两个表并返回team带有players属性的对象,这是一个只有id的数组,然后必须一个一个地查询到/players/:id

3:如果两个呼叫进行,一来/teams/:id和一个/teams/:id/players

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

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

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

sam*_*ime 8

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

如果你有时只需要团队,有时只需要一个团队的玩家,有时需要两个人,我会有3个不同的调用,可能是类似的东西/teams/:id,/players/:teamidplayer-teams/:teamid(或类似的东西).

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

话虽这么说,你也不想疯狂,因为你创建了一个过度膨胀的API.仔细考虑典型的用例并对其进行调用.不要只是为了它而实现你能想到的每一种可能的组合.记住你不需要它.


Eri*_*ein 5

我建议类似的东西:

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}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用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"
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我不会同时实现查询字符串和/ teams /:id / players。您应该选择自己喜欢的一种。如果两者都做,则必须永远支持多种做同一件事的方式。如果我想要一个团队中的所有球员,我将为/ players提供一个可选的查询参数?teamName = MyTeam作为端点。至于第二点,是的,我可以选择/ teams /:id?expand = players。 (2认同)