以RESTful方式处理子资源

5

我一直在创建一个RESTful应用程序,但对于如何处理不返回所有资源实体或返回多个资源的请求(例如GET /resource/all请求),我还没有决定。请允许我花费一些时间来设置这个情况(我会尽量概括,以便适用于除我之外的其他人):

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

我的第一个问题涉及到这种子资源模式。由于您可能并不总是想要在获取产品时获取评论,因此可以通过另一个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,让用户GET每一条评论,而不是将他们打包到一个请求中。根据RESTful标准,我应该如何指示这个评论URI数组呢?我应该使用头部还是像下面这样在响应体中列出URI:

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

8

你的问题在于没有使用超媒体。超媒体具有专门保持到其他事物链接的元素。

你应该考虑使用HAL,因为这是一种同时也在JSON中出现的超媒体内容类型。

然后,你可以利用HAL中的链接提供对你的评论的引用。


1
超媒体绝对是这里前进的道路!感谢您引起了我的注意!看到hal+json和hal+xml,似乎XML更自然(<link>href对我来说感觉很正确),所以我想我会转换为XML,即使它可能会更冗长。您建议我如何决定是否将资源链接或嵌入响应中?它应该是请求中可以指定的内容吗? - Bailey Parker
JSON Hyper-Schema标准可以为您现有的数据提供超文本解释,而无需改变您的JSON数据格式。它还可以指定表单,我认为HAL缺少这一点。 - cloudfeet

1
关于你的第一个问题(标题或正文),绝对不要发明自己的自定义标题。有些人会争辩说你应该使用链接标题,但我认为你会发现有很多需要嵌套链接的地方,所以应该将它们放在正文中。
如何指示reviews/资源的URI或其中的URI列表完全取决于您选择用于表示每个资源的媒体类型。例如,如果您使用HTML,可以使用锚标记。如果您使用纯JSON,它没有超媒体语法,您将不得不花费一些时间在API文档中描述哪些值是URI,通过指定特殊键来提名它们,或者用类似{"link": "reviews/123"}的特殊语法包装它们,或者使用相关模式文档。
看看Shoji,这是一种基于JSON的媒体类型,专门设计用于这种子资源模式。

1

JSON Schema标准可能会对您有所帮助,特别是超级模式。

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

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

href的值是一个URI模板 - 例如,如果您的数据包括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") 上的数据。

Jsonary JavaScript库有一个入门捆绑包,其中包括一个“通用客户端”——可点击的链接、表单输入的弹出窗口等。 - cloudfeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接