How should HATEOAS-style links be implemented for RESTful JSON collections?

两盒软妹~` 提交于 2019-11-29 20:09:48

Please don't dismiss HAL so quickly just because it looks a little bloated (in its JSON form, it's quite minimal).

HAL is to JSON what HTML is to plain text.

It adds hyperlinks. You need hyperlinks and a commonly understood representation format (such as HAL or Collection+JSON) for REST. You also need HATEOAS for REST, without HATEOAS it isn't REST! HATEOAS requires hyperlinks of course.

In your case, you are trying to build a collection resource. The IANA-registered relation for that is "item" (with reverse relation "collection"). Here is the representation in HAL for a People collection:

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

Note:

  • The primary data for this collection comes from _links.item[]. These are the items in the collection. The full (or at least some additional) data for each item is available in the _embedded array. If the client needs these additional data, it must find them by searching through _embedded[n]._links.self.href for each n. This is a design constraint of HAL. Other hypermedia representation formats have similar constraints (though perhaps going in the other direction).

  • I have added a title value for each member of the item array. This can appear between the opening and closing anchor tags if rendering to HTML, or as the text of a menu item in the client, without need for further processing of the representation by the client.

  • There are no ID parameters. All references to other resources are exposed as hyperlinks. A client should not have to "build" a URL by gluing an ID into a URL at some pre-defined place. This constitutes out-of-band information which inhibits independent changes to the client and server.

  • All of your hyperlinks should be absolute, since relative URLs may cause problems. All of your relations should be either listed on that IANA page or use a URI to define them. Ideally, that URI should be a dereferencable HTTP URL with documentation about the relation at the other end.

Willie Wheeler

It seems that JSON linking isn't a settled issue yet. There are several contenders:

References

First, I don't believe API's which have endpoints that return collections (JSON arrays) are truly RESTful. However, most "REST" API's bend the rules here.

I recently developed a REST API for the NextBus XML feed called restbus that returns collections from some endpoints while using HATEOAS style hypertext links. Here is a sample of the structure I used:

{
  // ... 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!"
      }
    ]
  }

}

It doesn't try to follow any of the popular JSON linking strategies out there (or their associated media types) like HAL et al. because they don't appear to be on the IETF Standards Track (yet). Instead the link object target attributes and link relation values meet RFC 5988 Web Linking specifications as much as possible.

You can see more details about the restbus hypertext link structure.

You may try to look at Restful object specification. That guys create concrete API. As I don't like the whole idea, there is a many practical solutions you can grab from them.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!