【问题标题】:Updating a collection the RESTful way以 RESTful 方式更新集合
【发布时间】:2018-04-04 11:58:52
【问题描述】:

我的情况类似于购物车。我有一组具有已知 ID 的产品,然后我想创建一个修改价格的子集,然后再修改这个子集

超集

[{  
   "productId":1,
   "price":1.99
},
{  
  "productId":2,
  "price":2.99
},
{  
  "productId":3,
  "price":3.99
},
{  
   "productId":4,
   "price":4.99
}]

...

修改子集

[{  
   "productId":1,
   "price":1.59
},
{  
  "productId":3,
  "price":2.59
}]

那我想再次修改子集的样子

[{  
   "productId":1,
   "price":1.79
},
{  
  "productId":2,
  "price":3.59
}]

我能想到的只是客户端发送一个类似

的 POST 请求
{  
   "productsAdded":[  
      {  
         "productId":2,
         "price":3.59
      }
   ],
   "productsModified":[  
      {  
         "productId":1,
         "price":1.79
      }
   ],
   "productsDeleted":[  
      {  
         "productId":3,
         "price":2.59
      }
   ]
}

限制是我想避免多次调用正确的动词而不发送整个子集。由于实际对象有更多字段,并且子集中有数千个对象。然后更新保存状态触发一个长时间运行的触发并忘记任务。

我看到的问题是客户端可能必须创建一个 状态和服务器必须从消息中重建状态。

这可能不是一个坏方法,但我想知道是否有替代解决方案

【问题讨论】:

  • 您的超集和子集缺乏一致性。
  • @AlanLarimer 这是设计使然,我希望子集中的产品具有与原始产品不同的价格,并且能够修改它们以及我在子集中可能拥有的任何其他字段。我想在这里调用集合集可能不太正确
  • 我把它读作 Superset -> Subset -> ModifiedSubset,但你实际上是在说明 Superset -> ModifiedSubset -> AgainModifiedSubset?
  • 是的,这就是我的意思。子集实体只需要具有来自超集的 id(不必担心创建 ID)并且可以多次修改而不会影响超集。将其视为用户可以创建、更新、删除的产品价格的覆盖,并且所做的所有更改都需要在单个事务中发生

标签: rest api api-design


【解决方案1】:

以 RESTful 方式更新集合

Atom Publishing Protocol 是围绕在 REST 架构风格中修改原子条目集合的想法而构建的。您可以先查看该设计。

我能想到的只是客户端发送一个类似的 POST 请求

这与JSON Patch 表示非常接近。

这个想法是,如果客户端和服务器对媒体类型有相同的(通常是标准化的)理解,那么即使它们是独立开发的,它们也可以继续协作。

因此,使用 POST 将更改的 JSONPatch 表示形式传递给资源是一个很好的起点;如果您不喜欢 JSONPatch(可能是因为它与域无关),您可以定义自己的更具体的媒体类型并使用它。

(注意:虽然消息类型称为“patch”,但您实际上并不需要在 API 中使用PATCH method。单独使用 POST、单独使用 PATCH 或两者都是可接受的替代方案。)

【讨论】:

  • 有趣,从来不知道 JSON Patch。它似乎与增加混乱的 HTTP PATCH 不同。我会调查一下,这似乎是我正在尝试做的标准化版本
【解决方案2】:

您提出的解决方案包含您提到的所有注意事项以及更多内容。建议:

  1. 通过独立的请求单独修改每个对象,使用 适当的 HTTP 动词 POST、PUT、PATCH、DELETE。
  2. 返回要在服务器上处理的整个集合,使用 适当的 HTTP 动词 PUT。
  3. 使用适当的 HTTP 动词 PATCH 返回要在服务器上处理的部分集合。

其他参考链接:

【讨论】:

  • 他绝对是按照规范使用 POST 动词。
  • POST 用于创建新实体。因此,除非 modification 是一个正在创建的实体并返回对它的新引用以便以后可以检索它,否则 POST 是不正确的。
  • tools.ietf.org/html/rfc7231#section-4.3.3: "POST 方法请求目标资源根据资源自身的特定语义处理请求中包含的表示。例如,POST 用于以下功能(以及其他) : [...] 将数据附加到资源的现有表示中。”
  • 您误读了规范。 “根据资源自己的特定语义处理请求中包含的表示”不是“创建资源”,而是“对资源的内容做某事”。当您需要做其他动词没有提供给您的任何事情时,POST 是一个包罗万象的动词。以下是关于使用 POST 执行非创建操作的适当性的讨论:roy.gbiv.com/untangled/2009/it-is-okay-to-use-post。作者是 Roy Fielding,他定义了 REST 并编写了 HTTP 规范。
猜你喜欢
  • 1970-01-01
  • 2015-04-22
  • 1970-01-01
  • 2014-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-26
相关资源
最近更新 更多