skip to content

In OData 4.01 JSON, what do the metadata=minimal, metadata=full and metadata=none format parameters change in a response?

level: middleimportance: should knowfreq 18%

answer

  1. a parameter on the Accept header
  2. what can be computed is omitted
  3. context and etag survive minimal
  4. none still keeps nextLink and count
  5. 4.01 drops the odata. prefix

basics

~20 s

The metadata format parameter sets how much control information the service writes. Minimal omits whatever metadata lets a client compute but keeps context, etag, count, nextLink and deltaLink; full writes every id, link and type explicitly; none keeps only nextLink and count.

solid answer

~50 s

OData JSON responses carry **control information** - `@context`, `@id`, `@etag`, `@nextLink`, navigation and edit links, `@type` - next to the data. The client chooses how much with the `metadata` format parameter, e.g. `Accept: application/json;metadata=minimal`. **Minimal** removes what a client can compute from the metadata document and URL conventions (an entity's id is its canonical URL, a navigation link is the read URL plus the property name) but must keep context, etag, count, nextLink and deltaLink, plus any value that differs from the computed one. **Full** writes all of it explicitly, for clients that cannot compute it. **None** keeps only nextLink and count, so the client loses ETags and context and needs out-of-band knowledge. In 4.01 payloads the `odata.` prefix should be omitted (`@context`, `metadata=minimal`); payloads marked `OData-Version: 4.0` must keep it, and 4.01 consumers must accept both.

go deeper

for a junior

Know that OData JSON carries @-prefixed control information and that the Accept header's metadata parameter picks minimal, full or none.

for a middle

Explain which control information each level keeps, how a minimal client computes ids and links from conventions, and why none keeps nextLink and count.

for a senior

Spot the integration traps: none silently removes ETags and context, a client matching only @odata.etag breaks on 4.01, and missing ids mark transient entities.

for a principal

Decide which level a fleet of clients should request, trading payload size against clients that must ship the model and URL rules to compute what was omitted.

## Data and control information An OData JSON payload mixes two things: the entity's **properties** (`"Name": "Widget"`) and **control information** - name/value pairs whose names start with `@` and that describe the payload rather than the data. The main ones are: - `@context` - the **context URL**: the metadata document URL plus a fragment saying what the payload is (`$metadata#Customers/$entity`). When present it must be the first property of the response. - `@id` - the **entity-id**, by convention identical to the entity's canonical URL. - `@etag` - the entity's **ETag**, used for conditional updates. - `@nextLink` and `@count` - the link to the next page of a partial collection and a requested total count. - `@deltaLink` - the link for fetching later changes when change tracking was requested. - `@editLink`, `@readLink`, `@navigationLink`, `@associationLink`, `@type` - links and type names a client could otherwise derive. ## How the client asks The level is a **format parameter** on the media type, sent in the `Accept` header (or the `$format` query option): ```http GET https://sales.example.com/service/Customers('ALFKI') Accept: application/json;metadata=full ``` Services must reject format parameters they do not know or support. If a client sends `OData-MaxVersion` and names no level, the service must return at least minimal control information. ## The three levels | Control information | minimal | full | none | |---|---|---|---| | `context` | yes (root, plus where the set cannot be inferred) | yes | no | | `etag` | yes | yes | no | | `count`, `nextLink` | yes, when applicable | yes | **yes**, when applicable | | `deltaLink` | yes, if requested | yes | not valid on a delta request | | `id`, `editLink`, `readLink`, navigation links | only when they differ from computed values | yes | no | | `type` | when it differs from the declared type | when not inferable from the value | no | 1. **minimal** - the service should remove control information a client can compute from the metadata document. The client computes the entity-id from the entity set and key, a navigation link from the read URL plus the property name, and an association link by adding `/$ref`. Whenever the real value differs from the computed one - an entity whose key fields were not selected, a non-canonical id - the service must write it, and the written value wins. 2. **full** - the service must include all control information explicitly. Payloads grow, but a client that cannot or will not read metadata can follow every link it is given. 3. **none** - the service should omit everything except `nextLink` and `count`, which it must keep so paging and counting still work. The client gets no context URL, no ids and no ETags, so it needs out-of-band knowledge of the model and its URLs. The JSON format also declares it not valid on a delta request. ## Consequences a client feels - **Concurrency:** under none, entities in a collection carry no ETag. A client that updates with `If-Match` must take the token from an `ETag` header on a single-entity read, or ask for minimal. - **Identity:** under minimal, a missing `@id` means "use the canonical URL". A 4.01 client must treat an entity with neither an id nor a full set of key properties as **transient** - it cannot be reread or updated. - **Metadata versioning:** `@metadataEtag` may appear under minimal or full so a client can check that its cached metadata matches the payload. ## The odata. prefix in 4.01 In OData 4.0 the parameter is `odata.metadata` and control information is spelled `@odata.context`, `@odata.etag` and so on. OData 4.01 lets both be written without the prefix: `metadata=minimal`, `@context`, `@etag`. Payloads with `OData-Version: 4.0` must use the prefix; 4.01 payloads should omit it; and a conforming 4.01 consumer must interpret control information with or without it. A client that matches only on `@odata.etag` breaks against a 4.01 service. Receivers must also ignore control information and annotations they do not recognise rather than fail. ## Choosing a level - **minimal** suits most clients that ship or download the model: the smallest payload that still carries ETags, paging links and context. - **full** suits generic or hypermedia-driven clients - explorers, form generators - that would rather follow links than compute them, and clients facing services whose URLs do not follow the conventions. - **none** suits a bulk extract with a fixed, known schema that never updates what it reads; it gives up context, ids and per-entity ETags in exchange for the leanest payload. The level is a per-request choice, so one client can read lists with minimal and switch to full for a screen that needs every link.

  • Why does a metadata=minimal client still need the metadata document?
    Minimal omits whatever can be computed, so the client must compute it: the entity-id from the entity set and key properties, navigation links from the read URL plus the property name, and types from the declared model. Without the model and the URL conventions those values are lost, which is exactly why `metadata=full` exists for clients that cannot compute them.
  • When does @id still appear in a metadata=minimal response?
    When the client cannot compute it: any of the entity's key fields were omitted from the response, for example by a projection, or the entity-id is not identical to the canonical URL after normalisation. A 4.01 entity with neither an id nor its full key is treated as transient and cannot be reread or updated.

saying these in an interview costs you the question

  • metadata=none also drops nextLink, so a paged result cannot be continued.
  • metadata=minimal omits ETags, so every entity must be reread before an update.
  • metadata=full returns more data properties than minimal does.
  • A 4.01 client may reject @context because only @odata.context is valid.
  • metadata=none costs nothing, because the client can compute whatever was left out.