JSON-LD @context
Where it goes
An application/json body can't carry an @context. An application/ld+json body must carry one, and the request can't then also send a context Link header. A request takes at most one context Link header, and in an array body every item carries the same @context.
The @context sits at the top level of the payload. One further down, inside an attribute, a value, a geometry or a languageMap, is refused. A JsonProperty's json is carried verbatim, so it is exempt.
An @context is a string, an object, null, or an array of those. Anything else is refused.
What it may hold
A user @context that declares a JSON-LD scoped context is refused, whether it arrives in the body, in a Link header or through a remote context it references.
The built-in W3C Data Integrity context is the one exception. It declares scoped contexts of its own, but the core @context names it for ngsildproof, so Andromeda treats it as part of the core @context and accepts a user @context that names it. Proofs covers what it is used for.
A cycle of @context references is refused, and so are references nested more than eight levels deep.
When a remote @context can't be fetched, the answer is 504 LdContextNotAvailable. One that is fetched but isn't JSON, or has no top-level @context, is refused.
The core @context always wins. A user context can't redefine a core term, so such a term keeps its core meaning and falls under the rule for reserved names.
How a body is read
A request body is read under the @context it was sent with. A member written @id or @type is read as id or type. A member written under a term your @context defines for a core term is read as that core term, in every body. With {"kind": "@type"} in your @context, a member kind is read as type, and with {"v": "https://uri.etsi.org/ngsi-ld/hasValue"} a member v is read as value. A type value that names a core class through such a term is read as that class.
A member written in the shape its term's container gives is read as if it had been written without the container.
- Under a
@setterm, an array of one is its single value. - Under a map container (
@index,@id,@type,@graph), an object of one key is the value under that key. - Under a map container, an object of several keys is the array of the values under its keys, in written order. A value that is itself an array gives its elements their places in it.
- The members under an alias of
@nestare members of the object that holds it.
An array of several elements under a @set term is read as written. So is JSON a body holds as data, and so is any spelling your context doesn't define. Without the aliasing context, {"kind": "Property", "v": 5} is therefore a concise Property whose value is that whole object.
How a response is written
A response names id, type and the core terms the way the core @context spells them, whatever your @context aliases. When a stored entity is read under a context with terms that alias core terms, a @set container, a map container (@index, @id, @type, @graph) or an alias of @nest, it is written without any of them. The result is always in the NGSI-LD shape.
JSON-LD @context covers how Andromeda builds response contexts and fetches remote ones.