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

u3r8eeie  于 2022-12-05  发布在  其他
关注(0)|答案(4)|浏览(121)

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

{
    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" 
]

这意味着我必须将数组 Package 在容器对象中。

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

但是它不同于单一资源,所以我将使记录的行为类似于集合,并将其 Package 在容器中......

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

从表面上看,这似乎是一个非常简洁的解决方案。生成的JSON更深了一层,但是已经实现了HATEOAS,所以这一切都很好,对吗?一点也不好。当我回到集合时,真实的的问题出现了。现在单个资源已经被 Package 在容器中,以便与集合保持一致。现在必须改变集合才能反映变化。而这就是它变得丑陋的地方。非常丑陋。现在集合看起来像这样...

{
    "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吻别吗?

368yc8dk

368yc8dk1#

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

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

它添加了超链接。对于REST,您需要超链接和一种通常理解的表示格式(如HAL或Collection+JSON)。对于REST,您还需要HATEOAS,没有HATEOAS就不是REST!HATEOAS当然需要超链接。
在本例中,您尝试构建一个集合资源。该集合的IANA-registered relation为“item”(反向关系为“collection”)。以下是People集合在HAL中的表示:

{
    "_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来找到它们。其他超媒体表示格式具有类似的约束(尽管可能是在另一个方向上)。
  • 我已经为item数组的每个成员添加了一个title值。如果呈现为HTML,或者作为客户端中的菜单项的文本,这可以出现在开始和结束锚标记之间,而不需要客户端对表示进行进一步处理。
  • 没有ID参数。所有对其他资源的引用都以超链接的形式公开。客户端不应通过将ID粘贴到某个预定义位置的URL中来“构建”URL。这构成了带外信息,禁止对客户端和服务器进行独立更改。
  • 所有的超链接都应该是绝对的,因为相对URL可能会引起问题。所有的关系都应该列在IANA页面上,或者使用URI来定义它们。理想情况下,URI应该是一个可取消引用的HTTP URL,另一端有关于关系的文档。
bweufnob

bweufnob3#

首先,我不相信具有返回集合(JSON数组)的端点的API是真正的RESTful。
我最近开发了一个名为restbusNextBus XML feed的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链接策略(或其相关的媒体类型),如HALetal .,因为它们似乎还没有出现在IETF Standards Track上。相反,链接对象目标属性链接关系值尽可能满足RFC 5988 Web Linking specifications
您可以看到有关restbus超文本链接结构的更多详细信息。

ovfsdjhp

ovfsdjhp4#

你可以试着看看Restful object specification。那些家伙创建具体的API。因为我不喜欢整个想法,有很多实际的解决方案,你可以从他们那里抓到。

相关问题