为了简单起见并避免命名冲突,我一直在我的记录资源中捆绑链接......
{
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:
},
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再见,迫使我过度复杂化数据结构?
答案 0 :(得分:34)
请不要因为它看起来有点臃肿而快速解散HAL(以JSON形式,它很小)。
HAL是JSON HTML是纯文本的。
它添加了超链接。您需要REST的超链接和通常理解的表示格式(例如HAL或Collection + JSON)。你还需要HATEOAS for REST,没有HATEOAS它不是REST! HATEOAS当然需要超链接。
在您的情况下,您正在尝试构建集合资源。 IANA-registered relation为“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,其中包含有关另一端关系的文档。
答案 1 :(得分:15)
似乎JSON链接尚未解决。有几个竞争者:
答案 2 :(得分:3)
首先,我不认为具有返回集合(JSON数组)的端点的API是真正的REST。但是,大多数“REST”API都在这里修改规则。
我最近为名为NextBus XML feed的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 et al。因为它们似乎不在IETF Standards Track(尚未)。相反,链接对象目标属性和链接关系值会尽可能地满足RFC 5988 Web Linking specifications。
您可以查看有关restbus hypertext link structure。
的更多详细信息答案 3 :(得分:1)
您可以尝试查看Restful object specification。那家伙创建具体的API。由于我不喜欢整个想法,因此您可以从中获取许多实用的解决方案。