skip to content

Describe how a HAL document (media type application/hal+json) is laid out. What do the reserved _links and _embedded properties hold, and what problem does _embedded solve?

level: middleimportance: should knowfreq 38%

answer

  1. resource = your JSON + _links + _embedded
  2. link object: href, templated, type, name, title, deprecation
  3. _embedded kills N+1, may be partial representations
  4. one object or an array - normalise on read
  5. curies compress custom rel URIs; no actions in plain HAL

basics

~20 s

A HAL resource is ordinary JSON plus two reserved keys. _links maps relation names to link objects with an href (optionally templated, type, title). _embedded maps relation names to full nested resources, so a client gets related data in one response instead of following every link.

solid answer

~50 s

HAL is deliberately minimal: a resource object is your own properties plus two reserved members. _links is a map from relation name to a link object or an array of link objects. A link object has href and optional templated, type, name, title, deprecation. Every resource should carry a self link. _embedded is a map from relation name to resource objects - full HAL resources, recursively, with their own _links. It exists to kill the N+1 problem: rather than returning a list of order links and forcing twenty follow-up requests, the collection embeds the orders themselves. The relation names in _embedded and _links mean the same thing; embedding is a transport optimisation, not a different relationship. The practical gotchas: any relation may be a single object or an array, so clients must normalise; custom relations are URIs, shortened via a curies link; and HAL has no notion of methods or forms - it tells you where to go, not how to submit a change.

code

json · 16 lines
json
{
  "count": 2,
  "_links": {
    "self":   { "href": "/orders?page=1" },
    "next":   { "href": "/orders?page=2" },
    "curies": [ { "name": "ex", "href": "https://example.com/rels/{rel}", "templated": true } ]
  },
  "_embedded": {
    "item": [
      { "id": "42", "total": 19.99,
        "_links": { "self": {"href":"/orders/42"}, "ex:cancel": {"href":"/orders/42/cancel"} } },
      { "id": "43", "total": 5.00,
        "_links": { "self": {"href":"/orders/43"} } }
    ]
  }
}

go deeper

for a junior

Describe the two reserved members, name href and self, and say _embedded includes related resources inline to save requests.

for a middle

Add link-object options, the single-versus-array pitfall, curies for custom relations, and that embedded copies may be partial.

for a senior

Weigh embedding against cacheability and payload size, and note HAL's lack of action semantics and the HAL-FORMS extension.

for a principal

Decide when HAL's minimalism is the right platform default versus a richer format, and require link generation from routing metadata rather than string building.

## The model HAL (Hypertext Application Language) defines just enough structure to make JSON linkable. A HAL document is a **resource object**: its own state as ordinary JSON members, plus two reserved members whose names begin with an underscore. **_links** - an object whose keys are link relation names and whose values are link objects (or arrays of them). A link object requires href and may carry: - templated: true when href is a URI template that must be expanded before use - type: a hint at the media type of the target - name: a secondary key used to disambiguate multiple links sharing a relation - title: human-readable label - deprecation: a URL explaining that this link is going away **_embedded** - an object whose keys are, again, relation names, and whose values are resource objects or arrays of them. Each embedded resource is a full HAL resource with its own _links and possibly its own _embedded, so documents nest. ## What _embedded is for Without embedding, a collection of a hundred orders is a hundred links and a hundred round trips. _embedded lets the server ship the representations it already has in hand. The relation name says what the embedded things are to the parent (item, author, related), exactly as a link would. Two consequences follow. First, an embedded resource may legitimately be a partial representation - the server may include only the fields worth listing - so clients that need everything follow the embedded resource's own self link. Second, embedding is a caching decision: an embedded copy is frozen inside the parent's cache entry, so highly volatile or independently cacheable sub-resources are often better left as links. ## Single versus array: the classic bug HAL permits a relation's value to be either one object or an array. A collection with one member can serialise as an object and with two as an array, and naive client code that iterates unconditionally breaks at exactly one item. Real clients normalise on read; some servers pin the choice per relation and document it. Expect this as a follow-up question. ## Custom relations and curies Extension relation names are URIs, which is verbose to repeat. HAL provides curies: a reserved link relation holding an array of templated links with name and href, letting documents write ex:approve instead of https://example.com/rels/approve. The client expands the prefix using the curie template to recover the full URI. Curies are a compression device for rel names; they change nothing semantically. ## What HAL does not do HAL has no actions, no methods, no field descriptions. A cancel link tells the client the URL, not that it should POST an empty body. Formats such as Siren, or the HAL-FORMS extension with its _templates member, exist to fill that gap. HAL also imposes no conventions for pagination, filtering, or errors - you layer those on yourself. ## Implementation shape Spring HATEOAS is a common concrete example: RepresentationModel carries the links, EntityModel wraps a payload object, CollectionModel wraps a list, Link and WebMvcLinkBuilder build hrefs from controller methods so they cannot drift from the routing table, and enabling the HAL hypermedia type makes the serializer emit _links and _embedded. That last point is the real value - links derived from the routes rather than string-concatenated.

  • Why is a HAL relation sometimes an object and sometimes an array, and how do clients cope?
    The spec allows both, so a server may emit a single link object for one target and an array when there are several - which means the same relation can change shape with the data. Robust clients normalise every relation to an array immediately after parsing. Servers can reduce the pain by always emitting arrays for relations that are conceptually multi-valued and documenting the choice.
  • When should a related resource be embedded rather than linked?
    Embed when the client almost always needs it and the server already has it, which removes a round trip. Link when the sub-resource is large, volatile, independently cacheable, or only occasionally needed, because an embedded copy is frozen into the parent's cached representation and inflates every response that carries it.

saying these in an interview costs you the question

  • Believing _embedded expresses a different relationship type than _links
  • Assuming a relation is always an array, so single-item responses crash the client
  • Expecting HAL to describe HTTP methods or form fields
  • Treating an embedded partial representation as the complete resource

context