REST API可以将多个资源作为单个复合资源返回吗?


10

我正在创建REST API,目前,我遇到以下问题:

  • Foo是第一资源。可以通过/foo/URI 应用CRUD操作。
  • Bar是第二资源。可以通过/bar/URI 应用CRUD操作。
  • 每个Foo都与零或一相关联Bar。之所以不将其Bar视为的子资源,Foo是因为Bar可以在Foo多个s 之间共享同一实例。因此,我认为最好通过独立的URI而不是通过URI访问它/foo/[id]/bar

我的问题是,在很多情况下,请求Foo实例的客户端也对关联的Bar实例感兴趣。当前,这意味着他们必须执行两个查询而不是一个。我想介绍一种允许通过单个查询获取两个对象的方法,但是我不知道如何为此建模。到目前为止,我想出了什么:

  • 我可以引入类似于以下内容的查询参数:/foo/[id]?include_bar=true。这种方法的问题在于,响应的资源表示形式(例如JSON结构)将需要看起来不同(例如,容器{ foo: ..., bar: ... }而不是仅序列化的容器Foo),这会使Foo资源端点“异构”。我不认为这是件好事。查询时/foo,无论查询参数如何,客户端都应始终获得相同的资源表示形式(结构)。
  • 另一个想法是引入一个新的只读端点,例如/fooandbar/[foo-id]。在这种情况下,返回像这样的表示形式没有问题{ foo: ..., bar: ... },因为那样的话,它只是fooandbar资源的“正式”表示形式。但是,我不知道这样的辅助端点是否真的是RESTful的(这就是为什么我在问题的标题中写了“ can”的原因。当然,从技术上讲这是可能的,但是我不知道这是一个好主意)。

你怎么看?还有其他可能性吗?


Foo和Bar之间的关系是什么术语?您能说Bar是Foo的父母吗?
内森·美林

如果Bar不与关联,则不能存在Foo。但是,正如我上面所写,多个可能Foo共享相同的Bar。可以创建一个Foo没有Bar关联的,因此我认为Bar不应将其视为父项。
ceran

1
我认为通过将域模型关系直接转换为URI并将资源等同于域实体,您遇到了一些我遇到的问题。可能有趣的是REST API必须是超文本驱动的。特别注意第4点
减毒活疫苗

Answers:


6

一个3级 REST API将返回你Foo也是一个链接指示相关Bar

GET /foo/123
<foo id="123">
  ..foo stuff..
  <link rel="bar" uri="/bar/456"/>
</foo>

然后,您可以在API中添加“向下钻取”功能,以允许链接导航;

GET /foo/123?drilldown=bar
<foo id="123">
  ..foo stuff..
  <link rel="bar" uri="/bar/456">
    <bar id="456">
      ..bar stuff...
    </bar>
  </link>
</foo>

向下钻取功能将位于API的前面并拦截响应。在将响应发回给呼叫者之前,它将进行深入查询并填写详细信息。

这在3级REST中是很常见的事情,因为它可以通过较慢的http大大减少客户端/服务器的聊天状态。我工作的公司正是使用此功能生产了3级REST API。

更新: 对于它的价值,这是它在JSON中的外观。这就是我们的API的结构方式。请注意,您可以嵌套钻取以拉出链接等的链接。

GET /foo/123?drilldown=bar

{
  "self": {
    "type": "thing.foo",
    "uri": "/foo/123=?drilldown=bar",
    "href": "http://localhost/api/foo/123?drilldown=bar"
  },
  "links": [
    {
      "rel": "bar",
      "rev": "foo",
      "type": "thing.bar",
      "uri": "/bar/456",
      "href": "http://localhost/api/bar/456"
    }
  ],
  "_bar": [
    {
      "self": {
        "type": "thing.bar",
        "uri": "/bar/456",
        "href": "http://localhost/api/bar/456"
      },
      "links": [
        {
          ..other link..
        },
        {
          ..other link..
        }
      ]
    }
  ]
}

有趣的是,我已经在使用超媒体链接/控件来消除与URI的紧密耦合,但是我还没有考虑过“下钻”的想法,这似乎很有希望。目前,我资源的每个JSON表示都包含一个links数组,每个条目都是一个链接对象,带有reluri字段(类似于您的xml示例)。我是否应该向每个链接对象添加第三个字段(例如data)?有什么标准吗?
ceran

向下钻取并不是真正的休息功能,因此没有标准(至少我知道)。
Qwerky

我在我们的应用程序中使用了一些提议的标准,例如stateless.co/hal_specification.html。这与您的示例非常接近。
皮特·柯坎

4

如果所有查询的95%的人希望Foo,以及Bar,然后返回它里面的的Foo对象,当你请求Foo。只需添加一个属性bar(或关系的其他术语),然后将Bar对象放在那里。如果该关系不存在,则使用null。

我认为您对此太想了:)


我不应该想出这个数字(95%),对不起,这是一个错误。我想说的是,大部分请求同时对这两种资源都感兴趣。但是仍然有相当数量的请求仅对感兴趣Foo,并且由于每个请求的Bar内存都非常大(约为的大小的3到4倍Foo),Bar如果客户端未明确请求,我不想返回a 。
ceran

我们在聊多大?我怀疑这将会使多在传输时间差的,我喜欢干净的API超速
弥敦道美林
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.