Search code examples
resthateoas

How to format HATEAOS links in JSON reponse


I'm building an API that contains beer data. Each beer in the beer_lookup table has these properties:

{
    "beerid": "e2e73352-1cf3-4bd7-943a-e682c2498c09",
    "beername": "Barrel-Aged Mexican Cake (Bourbon)",
    "description": "",
    "abv": "10.5",
    "ibu": "",
    "status": "Verified",
    "dateadded": "2017-08-28T00:00:00"
}

In separate lookup tables I have brewery and style linked to a beer via intersect tables.

In the json response when asking for a beer from http://localhost:5000/api/beer/{beerid} I want to provide the beer object and ref links (HATEAOS style) to other aspects of the beer. My response looks like this currently, which I think is ok except for instances when beers can have multiple breweries (collaborations). How should I deal with multiple "rel": "brewery" links? Should _links contain an array called breweries or something? I know I can totally return whatever I want but i'm wondering if there is a standard for something like that.

{
    "value": {
        "beerid": "e2e73352-1cf3-4bd7-943a-e682c2498c09",
        "beername": "Barrel-Aged Mexican Cake (Bourbon)",
        "description": "",
        "abv": "10.5",
        "ibu": "",
        "status": "Verified",
        "dateadded": "2017-08-28T00:00:00"
    },
    "_links": [
        {
            "href": "http://localhost:5000/api/beer/e2e73352-1cf3-4bd7-943a-e682c2498c09",
            "rel": "self",
            "method": "GET"
        },
        {
            "href": "http://localhost:5000/api/brewery/32efb254-b418-4c59-bc30-5cec97e3d702",
            "rel": "brewery",
            "method": "GET"
        },
        {
            "href": "http://localhost:5000/api/brewery/989b1eaa-fe92-423b-a275-4895ed90da51",
            "rel": "brewery",
            "method": "GET"
        },
        {
            "href": "http://localhost:5000/api/style/2689dcb0-9419-43c8-918f-4fc411fc0f90",
            "rel": "style",
            "method": "GET"
        }
    ]
}

EDIT: Possibly going with this:

{
    "value": {
        "beerid": "e2e73352-1cf3-4bd7-943a-e682c2498c09",
        "beername": "Barrel-Aged Mexican Cake (Bourbon)",
        "description": "",
        "abv": "10.5",
        "ibu": "",
        "status": "Verified",
        "dateadded": "2017-08-28T00:00:00"
    },
    "_links": {
        "self": {
            "href": "http://localhost:5000/api/beer/e2e73352-1cf3-4bd7-943a-e682c2498c09"
        },
        "breweries": [
            {
                "href": "http://localhost:5000/api/brewery/32efb254-b418-4c59-bc30-5cec97e3d702"
            },
            {
                "href": "http://localhost:5000/api/brewery/989b1eaa-fe92-423b-a275-4895ed90da51"
            }
        ],
        "style": {
            "href": "http://localhost:5000/api/style/2689dcb0-9419-43c8-918f-4fc411fc0f90"
        }
    }
}

Solution

  • I want to provide the beer object and ref links (HATEAOS style) to other aspects of the beer.

    Awesome.

    You should probably look at the JSON hypermedia formats, rather than rolling your own.

    Not what you asked, though.

    Possibly going with this

    Maybe - I think it depends on how you expect clients to consume the links. Is the client expected to care which breweries link is which? Or are clients interested in breweries expected to load all of them?

    Think of a web page -- we include image links in html, but the client is expected to download and render all of them. Hyperlinks (defined by the a tag) are normally accompanied by some semantic content to allow the client to discriminate them.

    So your breweries might be a list of embedded objects with self links, rather than being links on the beer resource itself.

    The example on the HAL specification provides, I think, a decent illustration of the two options.