Search code examples
jsonweb-servicesrestwebhateoas

How to represent collections in HAL (JSON version) while following REST


Let's say I have a collection of books which we'll call a library. GET domain.com/library should return a list of books in the library in HAL compliant JSON. How should I format the JSON? How could I embed the book resources? Here is the format I'm currently thinking about:

{
  "books": [
      {
          "name": "Fight Club",
          "_links": {
              "self": { 
                  "href": "domain.com/library/Fight-Club"
              },
           },
           ...
      },
       ....
  ],
  "_links" : {
       "search": { 
           "href": "domain.com/library/search"
       },
       ...
   },
   "_embedded" : {
       "Fight Club": {
           "author": "Chuck Palahniuk",
           ...
           [Same links as above]
       }
   }
}

Solution

  • As the HAL specification was written, the _embedded object is intended for sub-resources of a given resource. So your bare-bones HAL JSON would look like this.

    {
        "_links": {
            "self": {
                "href": "/library"
            }
        },
        "_embedded": {
            "item": [{
                "_links": {
                    "self": {
                        "href": "/library/Fight-Club"
                    }
                },
                "author": "Chuck Palahniuk",
                "title":  "Fight Club"
            }]
        }
    }
    

    The immediate properties of the _embedded object are link relations. The item relation is a standard relation that means a resource is an item belonging to the context resource (in this case, your library). You can create custom link relation by using CURIEs.

    Notice the lack of a books array in the top-level object. You may include it if you wish, but it's merely a convenience. A HAL library will only be aware of what you put in _links and _embedded. See this discussion regarding collections in HAL and the human factor in deciding where to put your data.