嵌套对象的 RESTful 重新排序

Posted

技术标签:

【中文标题】嵌套对象的 RESTful 重新排序【英文标题】:RESTful reordering of nested objects 【发布时间】:2014-12-15 12:31:04 【问题描述】:

我有一个支持两个对象的 RESTful API,因此对象 A 包含嵌套对象 B 的有序列表:

Create object A               - POST  /a
Create object B and add to A  - POST  /a/<id>/b
Update object B in A          - PATCH /a/<id>/b/<id>

什么是更新特定 AB 对象顺序的 RESTful 方式?

选项 1: PATCH /a/&lt;id&gt; 用 json 内容替换 A.BsA 有一个嵌入的 Bs 列表,即 A.Bs,因此您可以替换该列表在整个过程中也改变了顺序。这依赖于客户端正确地重新提交整个列表。

选项 2: PATCH /a/&lt;id&gt; 用 json 内容替换 A.B_order 添加一个单独的B id 列表并让客户端更新它。这类似于选项 1,但不依赖于客户端重新提交所有对象。它确实需要服务器管理列表,在创建 B 时对其进行更新,并验证更新包含列表顺序更新时所需的所有 B id。

选项 3: PATCH /a/&lt;id&gt;/b 用 json 内容替换 A.Bs 与选项 1 相同,但 URL 不同

哪个最 RESTful 和清晰? 还有其他选择吗?

【问题讨论】:

顺便说一句,我使用 PATCH 进行部分更新,而不是 PUT 替换整个对象 为什么不改为 POST 呢? @richard POST 也可用于此类情况,但 PATCH 比 POST 更具体/语义正确,因此更适合。 我仍在试图找出restful-url 和普通的区别,因为对我来说它们实际上是相同的。这样,客户端不应该解释 URI,而只是将它们用作指向资源的指针。与通常的看法相反,URI 本身不包含任何路径逻辑,应该作为一个整体使用。您当然可以通过提供一组 URI 来“伪造”路径逻辑,这些 URI 总体上形成了一个可遍历的图。 HTTP 允许通过 PATCH 或 PUT 更新重叠资源进行部分更新。这具有对实际资源进行部分更新的效果 然而,与 PUT 不同的是,PATCH 实际上是一种客户端可以用来向服务器发送有关如何将当前资源修改为所需状态的分步指令的方法。客户端实际上是在告诉服务器如何转换资源而不是呈现最终输出。还需要所有指令都成功完成或根本不应用它们,这需要操作的一些事务性要求。正如 Eric 和 Evert 已经提出的那样,我也建议使用 JsonPatch 因此 【参考方案1】:

我建议使用RFC 6902 中定义的建议标准。具体来说,“移动”操作似乎正是您要寻找的。​​p>

【讨论】:

不错的参考,但至少对我来说这似乎有点过头了【参考方案2】:

鉴于 Foo 具有 Bars 并且 Bars 是资源(具有 ID 或链接),当您需要重新排序 foo.bars 时,我会建议:

'PUT /foos/:id/bars' 带有 ID 数组或正文中的链接。

但如果 Bars 不是资源(没有 ID),那么:

'PATCH /foos/:id' 带有 Foo 的主体,在 'bars' 属性中包括完整的新的 Foo.bars 数组。

【讨论】:

【参考方案3】:

我会问自己的问题是:“在这种情况下,‘订单’是什么意思”。

B 的具体实例之间没有顺序。它们都是独立的资源,并不真正“了解”每个订单。

鉴于此,您要更改的并不是真正的 B 资源。你要改变什么?

大概在某处有B 的集合。您对该集合执行GET 请求以获取B 的有序列表。您是否在/a/&lt;id&gt;/a/&lt;id&gt;/b 上获得该列表?。

无论该有序列表在哪里,我也会执行更改顺序的操作,因为该顺序是集合的“属性”。

因此,为了论证,假设您的“B 集合存在于/a/&lt;id&gt;b 上。那应该是什么格式?

好吧,一个好的 REST 服务将取代整个状态。因此,默认情况下,我会对该资源发出PUT 请求并完全替换整个资源。

如果您不喜欢这个想法并且想使用PATCH 仅更新集合的一部分(而不是其他),我想我会选择以下之一:

    使用标准格式,例如json-patch。 想出你自己的语法来描述这个。

选项 2 实现起来可能会简单得多,而且我也会尽可能保持格式简单。

如果您使用 HAL 之类的格式,则集合可能是链接列表。在这种情况下,我会使用如下语法:


  "_links": 
     "item": [
         "href": "/a/<id>/b/ordered-item-1" ,
         "href": "/a/<id>/b/ordered-item-2" 
      ]
  

如果您没有超媒体风格的 API,您可能会使用 id 并强制客户端在 url 中扩展 id。在这种情况下,我想格式可能如下所示:


   "items": [ 1, 3, 5, 2]

在每种情况下,为此定义您自己的媒体类型都是一个好主意,因为 PATCH 的这种格式对您的 api 具有特殊意义。例如:

application/vnd.jonathan.patch+json

【讨论】:

以上是关于嵌套对象的 RESTful 重新排序的主要内容,如果未能解决你的问题,请参考以下文章

ExpressJS - 嵌套/链接资源的 RESTful 路由设计

将两个值传递给嵌套的 restful 控制器

使用 flask-restful RequestParser 进行嵌套验证

2021-03-02 flask-restful传参

week05 restful api

在 RESTful URL 中具有嵌套资源的父 ID 背后的合理性