如何为RESTful JSON集合实现HATEOAS风格的链接?

tho*_*ter 35 rest json hateoas

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

{
    id: 211,
    first_name: 'John',
    last_name: 'Lock',
    _links: [
        { rel: 'self', href: 'htttp://example.com/people/211' }
    ]
}
Run Code Online (Sandbox Code Playgroud)

但是,我无法弄清楚如何在集合中实现链接.我花了很长时间在网上搜寻一些例子,除了使用不那么精益的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" 
]
Run Code Online (Sandbox Code Playgroud)

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

[
    people: [ {id:1,first_name:.....} ],
    links: [ { rel:parent, href:.... ]
]
Run Code Online (Sandbox Code Playgroud)

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

{
    person: {
        id: 211,
        first_name: 'John',
        last_name: 'Lock',
        _links: 
    },
    links:[
        { rel: 'self', href: 'htttp://example.com/people/211' }
    ] 
}
Run Code Online (Sandbox Code Playgroud)

从表面上看,这似乎是一个非常简洁的解决方案.由此产生的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"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

是否有更简单的解决方案来实现HATEOAS集合?或者我应该亲吻HATEOAS再见,迫使我过度复杂化数据结构?

Nic*_*nks 36

请不要因为它看起来有点臃肿而快速解散HAL(以JSON形式,它是非常小的).

HAL是JSON HTML到纯文本的内容.

它添加了超链接.您需要REST的超链接和通常理解的表示格式(例如HAL或Collection + JSON).你还需要HATEOAS for REST,没有HATEOAS它不是REST!HATEOAS当然需要超链接.

在您的情况下,您正在尝试构建集合资源.在IANA注册的关系,因为这是"项目"(具有反向关系,"收藏").以下是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" }
                }
            }
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:

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

  • titleitem数组的每个成员添加了一个值.如果呈现为HTML,则可以在开始和结束锚标记之间出现,或者作为客户端中的菜单项的文本,这可以在客户端进一步处理表示之前出现.

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

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


swi*_*ist 2

您可以尝试查看Restful 对象规范。这些人创建了具体的 API。由于我不喜欢整个想法,因此您可以从他们那里获取许多实用的解决方案。