Skip to content

Instantly share code, notes, and snippets.

@zdne
Last active June 5, 2019 12:47
Show Gist options
  • Save zdne/c0f91c9ba8ad0d48a597e6868123dc40 to your computer and use it in GitHub Desktop.
Save zdne/c0f91c9ba8ad0d48a597e6868123dc40 to your computer and use it in GitHub Desktop.
Explanation of HAL+JSON embedding

Embedding Related Resoruces in HAL

Often, I get questions about embedding resources with HAL http://stateless.co/hal_specification.html. Here is some of my recommendation illustrated on an example.

First of all, think of the _embedded as a courtesy of HAL so the API user does not have to make one more call to retrieve a resource that has a link relation with the current (self resource). Let's illustrate it on an example: A collection of applications and one application, where an application might have related, child applications. The link relations are as follow:

collection of applications resource ——application relation——> application resource

application resource ——child relation——> application resource

The same relations depicted as a finite state machine (automaton) diagram:

application finite state machine

Now let's make the HTTP request to retireve details about one application together with related child applications (if any):

GET /applications/1 HTTP/1.1
Accept: application/hal+json

Scenario 1: No Embed

This is the most important part. Everything should work without embedding. This is how you express that this (self) resource has 3 other resources that have the relation child to this resource:

{
  "_links": {
    "self": { "href": "/applications/1"},
    "child": [
      { "href": "/applications/2"},
      { "href": "/applications/3"},
      { "href": "/applications/4"}
    ]
  },
  "appName": "app1",
  "someDataField": "lorem ipsum"
}

Scenario 2: Embed

Now let's as a courtesy to the client you might provide some of the _links relation right away in the _embedded section. Note the relation identifier remains the same (the embedded resoure is still a child to this (self) resource). The embedded resoruces might have the child relation with other resoruces, but may not (see the /applications/2 - it has no children - that is resources with relation child)

{
  "_links": {
    "self": { "href": "/applications/1"}
  },
  "appName": "app1",
  "someDataField": "lorem ipsum",
  "_embedded": {
    "child": [
      {
        "_links": {
          "self": { "href": "/applications/2"},
          "child": []
        },
        "appName": "app2",
        "someDataField": "lorem ipsum",
      },
      {
        "_links": {
          "self": { "href": "/applications/3"},
          "child": [
            { "href": "/applications/5"},
          ]
        },
        "appName": "app3",
        "someDataField": "lorem ipsum",
      }
      {
        "_links": {
          "self": { "href": "/applications/4"},
          "child": [
            { "href": "/applications/5"},
            { "href": "/applications/7"},
            { "href": "/applications/8"}            
          ]
        },
        "appName": "app4",
        "someDataField": "lorem ipsum"
      }
    ]
  }
}

Scenario 3: Embed with embeds

Finally, you, in theory, can embed relations in already embedded resources, however, I'd not recommend it. Look at the /applications/3.

{
  "_links": {
    "self": { "href": "/applications/1"}
  },
  "appName": "app1",
  "someDataField": "lorem ipsum",
  "_embedded": {
    "child": [
      {
        "_links": {
          "self": { "href": "/applications/2"},
          "child": []
        },
        "appName": "app2",
        "someDataField": "lorem ipsum"
      },
      {
        "_links": {
          "self": { "href": "/applications/3"}
        },
        "appName": "app3",
        "someDataField": "lorem ipsum",
        "_embedded": {
          "child": [
            {
              "_links": {
                "self": { "href": "/applications/5"},
                "child": []
              },
              "appName": "app5",
              "someDataField": "lorem ipsum",
            }
          ]
        }
      }
      {
        "_links": {
          "self": { "href": "/applications/4"},
          "child": [
            { "href": "/applications/5"},
            { "href": "/applications/7"},
            { "href": "/applications/8"}            
          ]
        },
        "appName": "app4",
        "someDataField": "lorem ipsum"
      }
    ]
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment