38

为了简单起见并避免命名冲突,我一直在像这样在我的记录资源中捆绑链接......

{
    id: 211,
    first_name: 'John',
    last_name: 'Lock',
    _links: [
        { rel: 'self', href: 'htttp://example.com/people/211' }
    ]
}

但是,我无法弄清楚如何在集合中实现链接。我花了很长时间在网上搜索示例,除了使用不太精简的HAL之外,我无法解决我的问题。

[
    {id:1,first_name:.....},
    {id:2,first_name:.....},
    {id:3,first_name:.....}, 
    "_links": "Cant put a key value pair here because its an-array" 
]

这意味着我必须将数组包装在一个容器对象中。

{
    people: [ {id:1,first_name:.....} ],
    links: [ { rel:parent, href:.... ]
}

但是它与单一资源不同,所以我要让记录表现得像集合一样,并将其包装在一个容器中......

{
    person: {
        id: 211,
        first_name: 'John',
        last_name: 'Lock'
    },
    links:[
        { rel: 'self', href: 'htttp://example.com/people/211' }
    ] 
}

从表面上看,这似乎是一个非常巧妙的解决方案。生成的 JSON 更深一层,但 HATEOAS 已经实现,所以没问题吧?一点也不。当我回到收藏品时,真正的刺痛来了。现在单个资源已经被包装在一个容器中以便与集合保持一致,现在必须更改集合以反映更改。这就是它变得丑陋的地方。十分难看。现在集合看起来像这样......

{
    "people": [
        {
            "person": {
                ....
            },
            "links" : [
                {
                    "rel": "self",
                    "href": "http://example.com/people/1"
                }
            ]
        },
        {
            "person": {
                ....
            },
            "links" : [
                {
                    "rel": "self",
                    "href": "http://example.com/people/2"
                }
            ]
        }
    ],
    "links" : [
        {
            "rel": "self",
            "href": "http://example.com/people"
        }
    ]
}

是否有更简单的解决方案来为集合实施 HATEOAS?或者我应该和 HATEOAS 告别,因为它迫使我过度复杂化数据结构?

4

4 回答 4

39

请不要仅仅因为 HAL 看起来有点臃肿(在它的 JSON 形式中,它非常小)就这么快就将其关闭。

HAL 之于 JSON 就像 HTML 之于纯文本。

它添加了超链接。REST 需要超链接和普遍理解的表示格式(例如 HAL 或 Collection+JSON)。您还需要 HATEOAS 来实现 REST,没有 HATEOAS 就不是 REST!HATEOAS 当然需要超链接。

在您的情况下,您正在尝试构建一个集合资源。IANA 注册的关系是“item”(具有反向关系“collection”)。以下是 HAL 中 People 集合的表示形式:

{
    "_links": {
        "self": { "href": "http://example.com/people" },
        "item": [
            { "href": "http://example.com/people/1", "title": "John Smith" },
            { "href": "http://example.com/people/2", "title": "Jane Smith" }
        ]
    },
    "_embedded": {
        "http://example.com/rels#person": [
            {
                "first_name": "John",
                "last_name": "Smith",
                "_links": {
                    "self": { "href": "http://example.com/people/1" },
                    "http://example.com/rels#spouse": { "href": "http://example.com/people/2" }
                }
            },
            {
                "first_name": "Jane",
                "last_name": "Smith",
                "_links": {
                    "self": { "href": "http://example.com/people/2" },
                    "http://example.com/rels#spouse": { "href": "http://example.com/people/1" }
                }
            }
        ]
    }
}

笔记:

  • 此集合的主要数据来自_links.item[]. 这些是集合中的项目。_embedded数组中提供了每个项目的完整(或至少一些附加)数据。如果客户端需要这些附加数据,它必须通过搜索_embedded[n]._links.self.href每个n. 这是 HAL 的设计约束。其他超媒体表示格式也有类似的限制(尽管可能会朝另一个方向发展)。

  • 我为数组title的每个成员添加了一个值。item如果呈现为 HTML,它可以出现在开始和结束锚标记之间,或者作为客户端中菜单项的文本,而不需要客户端进一步处理表示。

  • 没有 ID 参数。所有对其他资源的引用都显示为超链接。客户端不必通过在某个预定义位置将 ID 粘贴到 URL 中来“构建”URL。这构成了禁止对客户端和服务器进行独立更改的带外信息。

  • 您的所有超链接都应该是绝对的,因为相对 URL 可能会导致问题。您的所有关系都应该列在该 IANA 页面上,或者使用 URI 来定义它们。理想情况下,该 URI 应该是一个可取消引用的 HTTP URL,其中包含有关另一端关系的文档。

于 2013-08-06T14:41:21.957 回答
15

似乎 JSON 链接还不是一个已解决的问题。有几个竞争者:

参考

于 2014-12-21T20:02:58.293 回答
3

首先,我不相信具有返回集合(JSON 数组)的端点的 API 是真正的 RESTful。但是,大多数“REST”API 都在此处违反规则。

我最近为NextBus XML 提要开发了一个名为restbus的 REST API,它在使用 HATEOAS 样式的超文本链接时从一些端点返回集合。这是我使用的结构示例:

{
  // ... SF-Muni resource from restbus API ...

  _links: {
    self: {
      href: "http://localhost:3535/agencies/sf-muni",
      type: "application/json",
      rel: "self",
      rt: "agency",
      title: "Transit agency 'sf-muni'."
    },
    to: [
      {
        href: "http://localhost:3535/agencies/sf-muni/routes",
        type: "application/json",
        rel: "describedby",
        rt: "route",
        title: "A collection of routes for transit agency 'sf-muni'."
      },
      {
        href: "http://localhost:3535/agencies/sf-muni/vehicles",
        type: "application/json",
        rel: "describedby",
        rt: "vehicle",
        title: "A collection of vehicles for transit agency 'sf-muni'."
      }
    ],
    from: [
      {
        href: "http://localhost:3535/agencies",
        type: "application/json",
        rel: "bookmark",
        rt: "agency",
        title: "A collection of transit agencies. This is the API root!"
      }
    ]
  }

}

它不会尝试遵循任何流行的 JSON 链接策略(或其关联的媒体类型),HAL 。因为它们似乎还没有出现在IETF 标准轨道上。相反,链接对象目标属性链接关系值尽可能满足RFC 5988 Web Linking 规范。

您可以查看有关restbus 超文本链接结构的更多详细信息。

于 2014-02-18T23:53:04.367 回答
2

您可以尝试查看Restful object specification。那家伙创建了具体的API。由于我不喜欢整个想法,因此您可以从中获取许多实用的解决方案。

于 2013-07-27T06:25:10.847 回答