RESTful处理子资源

时间:2012-01-07 00:06:29

标签: api http rest

我一直在创建RESTful应用程序,并且未决定如何处理不返回资源的所有实体或返回多个资源的请求(GET /resource/all请求)。请允许我稍微设置一下情况(我会尝试尽可能地概括这一点,以便它可以适用于我以外的其他人):

假设我正在创建一个产品API。为简单起见,假设它返回JSON(在发送正确的接受标头之后)。可以在/product/[id]访问产品。产品的评论可以在/products/[id]/review/[id]访问。

我的第一个问题在于这种子资源模式。由于您在获取产品时可能并不总是想要评论,因此可以通过其他URI访问它们。根据我的内容,我应该包含请求的URI,该URI将返回产品请求响应中产品的所有审核URI。我应该如何解决这个问题,以便它遵守RESTful标准?它应该是Reviews-URI: /product/123/review/all之类的标题,还是应该在响应正文中包含URL,如下所示:

{ 'name': 'Shamwow',
  'price': '$14.99',
  'reviews': '/product/123/review/all'
}

我的第二个问题是/product/[id]/review/all请求应如何运作。我听说我应该发送所有评论的URL并让用户获取每个评论,而不是将所有评论打包成一个请求。我应该如何根据RESTful标准指出这一系列的评论URI?我应该使用标题或列出响应正文中的URI,如下所示:

{ 'reviews': [ '/product/123/review/1',
               '/product/123/review/2',
               '/product/123/review/3'
             ]
}

3 个答案:

答案 0 :(得分:7)

您的问题是您没有使用超媒体。超媒体特别具有与其他事物相关联的元素。

您应该考虑HAL,因为这是一个恰好也是JSON的超媒体内容类型。

然后,您可以利用HAL中的链接为您的评论提供参考。

答案 1 :(得分:1)

关于你的第一个问题(标题或正文),绝对不要发明你自己的自定义标题。有些人会争辩说你应该使用Link header,但我认为你会发现很多需要嵌套链接,并且应该将它们保存在体内。

如何指示reviews/资源的URI或其中的URI列表,完全取决于您选择用于表示每个资源的媒体类型。例如,如果您使用的是HTML,则可以使用锚标记。如果您使用的是没有超媒体语法的普通JSON,您将不得不在API的文档中花一些时间来描述哪些值是URI,或者通过使用特殊键指定它们,或者使用特殊语法(如{ {1}}或相关的架构文档。

看看Shoji,这是一种基于JSON的媒体类型,它是为这种子资源模式明确设计的。

答案 2 :(得分:1)

JSON Schema标准可能会对您有所帮助,特别是Hyper-Schemas。

它允许您定义如何从数据中提取链接URI,以及它们的“rel”是什么 - 实质上是将您的JSON数据转换为超媒体。因此,对于您的第一部分数据,您可能会编写如下模式:

{
    "title": "Product",
    "type": "object",
    "properties": {...},
    "links": [
        {"rel": "reviews", "href": "{reviews}"}
    ]
}

href的值为URI Template - 例如,如果您的数据包含productId,那么您可以将href的值替换为"/product/{productId}/review/all" }。

对于示例数据的第二位(评论列表),您可能有这样的架构:

{
    "type": "object",
    "properties": {
        "reviews": {
            "type": "array",
            "items": {
                "links": [
                    {"rel": "full", "href": "{$}"}
                ]
            }
        }
    }
}

href的URI模板中,{$}的特殊值表示“JSON节点本身的值”。因此,Hyper-Schema指定reviews数组中的每个项都应替换为指定URL(rel="full")处的数据。