json - 应该如何为 RESTful JSON 集合实现 HATEOAS 样式的链接?

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

{
    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 已经实现,所以没问题吧?一点也不。当我回到收藏品时,真正的刺痛来了。现在单个资源已经被包装在一个容器中以便与集合保持一致,现在必须更改集合以反射(reflect)更改。这就是它变得丑陋的地方。十分难看。现在集合看起来像这样......

{
    "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 告别,因为它迫使我过度复杂化数据结构?

最佳答案

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

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

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

在您的情况下,您正在尝试构建一个集合资源。 IANA-registered relation因为那是“项目”(具有反向关系“集合”)。以下是 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 数组中提供了每个项目的完整(或至少一些附加)数据。如果客户端需要这些额外的数据,它必须通过为每个 n 搜索 _embedded[n]._links.self.href 来找到它们。这是 HAL 的设计约束。其他超媒体表示格式也有类似的限制(尽管可能会朝另一个方向发展)。

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

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

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

https://stackoverflow.com/questions/17877220/

相关文章:

c# - 使用 JSON.NET 序列化/反序列化对象字典

json - 从 Java 类生成 JSON 模式

asp.net-mvc - MVC ajax json 发布到 Controller 操作方法

c# - ASP.NET Core - 当前上下文中不存在名称 'JsonRequestBehavi

ruby-on-rails - 销毁记录时应该渲染什么?

json - 使用 jq 从 JSON 输出中提取特定字段

JSON Schema - 根据另一个字段的值指定字段

jquery - 使用 jQuery grep() 过滤 JSON 数组

json - 在 node package.json 中,使用额外参数从另一个脚本调用脚本,在这种情

json - Play Framework - 向 JSON 对象添加字段