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:
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
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"
}
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"
}
]
}
}
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"
}
]
}
}