skip to content

JSON and XML Encoding

The yang-data JSON and XML media types, module-qualified member names in JSON, and Accept-based negotiation. The JSON namespace rules trip anyone who assumes it is plain JSON.

on this pageshow

questions

5

Why does a RESTCONF server reject a JSON body whose member names are unqualified, and where does RFC 7951 require module prefixes?

level: middleimportance: must knowfreq 18%

answer

  1. JSON has no xmlns attribute
  2. the module name, not the YANG prefix
  3. the top level, then wherever the module changes
  4. augmented children break the inheritance

basics

~20 s

RFC 7951 requires every top-level JSON member to be named module:node, and a child to be qualified again only when its module differs from its parent's, as with augmented nodes; without those names the server cannot map the body to its schema.

solid answer

~40 s

JSON has no namespace mechanism, so RFC 7951 builds one into member names. A member name is either *simple* (`mtu`) or *namespace-qualified* (`example-net:ports`), where the qualifier is the **name of the module** that defines the node, never its YANG `prefix`, and for a submodule the main module's name. The qualified form is required for every member of the top-level object and wherever a node's module differs from its parent's, typically a node added by `augment`; everywhere else the simple form is required, so over-qualifying is also wrong. A body built from a plain object such as `{"ports": {...}}` gives the server no module for its top-level node, so it cannot match the data to the schema and rejects it. Lists are arrays even with one entry.

go deeper

for a junior

Remember the shape: the first member is module:node, children of the same module are plain names.

for a middle

Explain both halves of the rule, qualify at the top and on a module change, use the simple form everywhere else, and why augment forces the change.

for a senior

Diagnose a rejected body quickly: missing top-level module, an augmented node left plain, a YANG prefix used instead of the module name, or a one-entry list sent as an object.

for a principal

Argue for generating RESTCONF bodies from the YANG schema rather than hand-built objects, and what that means for the tooling your automation depends on.

## Why JSON needs a naming rule at all A **YANG** data tree can mix nodes from many modules: one module defines a container, another **augments** it with extra leaves, and two modules may each define a node with the same identifier. The XML encoding separates them with XML namespaces. JSON has nothing comparable: a member name is just a string. **RFC 7951**, the JSON encoding of YANG data that RESTCONF uses for `application/yang-data+json`, therefore encodes the namespace into the member name itself (Section 4). ## The two forms of a member name RFC 7951's grammar is `member-name = [identifier ":"] identifier`, giving two forms: | Form | Example | Meaning | |---|---|---| | **simple** | `"mtu"` | the node is in the same module as its parent | | **namespace-qualified** | `"example-net:ports"` | the node is defined in module `example-net` | Three details trip people up: - The qualifier is the **module name**, not the short `prefix` a YANG module declares for itself. A module named `example-net` with `prefix "en"` is written `example-net:...` in JSON; `en:` means nothing to a JSON decoder. - A node defined in a **submodule** is qualified with the name of the **main module** the submodule belongs to. - The rule is mandatory in both directions: RFC 7951 says the qualified form MUST be used at the top level and where the namespace changes, and "in all other cases, the simple form of the member name MUST be used". Qualifying everything "to be safe" is non-conforming. ## Where qualification is required 1. **Every member of the top-level JSON object.** The outermost member has no parent to inherit from, so it always names its module. This holds for the body of a `PUT` to a deep resource too: RFC 8040's own example replaces one album with a body whose top-level member is `"example-jukebox:album"`, even though the URI already names the module. 2. **Wherever a node's module differs from its parent's.** The usual cause is `augment`: a leaf another module grafts into your container is qualified with *its* module's name, and its own children revert to simple names below it. 3. **Nowhere else.** A child defined in the same module as its parent is always simple. ```json { "example-net:ports": { "mtu": 1500, "example-qos:policy": { "limit": 10 } } } ``` Here `ports` and `mtu` come from `example-net`; `example-qos` augments `ports` with container `policy`, so `policy` is qualified and its child `limit` is simple again. ## What a hand-written body usually gets wrong A body produced by serializing an ordinary object fails in predictable ways: - **Unqualified top level**: `{"ports": {...}}` gives the server no module for `ports`, so it cannot find the node in its schema. - **Augmented node unqualified**: `"policy"` under `example-net:ports` names a node `example-net` never defined. - **YANG prefix instead of module name**: `"en:ports"` names a module that does not exist. - **Single list entry as an object**: RFC 7951 Section 5.4 encodes a YANG `list` as an **array of objects**, so a list with one entry is still `[ {...} ]`. - **Assuming key order matters**: in XML the list keys must come first; in JSON the order of members inside a list entry is arbitrary, because JSON objects are unordered. Which error a server reports for these is not fixed by the RFC: expect a `400 Bad Request` with an `ietf-restconf:errors` body whose `error-tag` is something like `unknown-element` or `malformed-message`, and read its `error-path` to find the node. ## Relation to the URI and to metadata The request URI follows the same idea: its first node carries the module name (`/restconf/data/example-net:ports`), and a node from another module is qualified again. That URI syntax belongs to RESTCONF's resource mapping; the body follows RFC 7951. Separately, RFC 7951 Section 5.7 reserves member names beginning with `@` for **metadata** (RFC 7952), such as the `"@mtu"` annotation RESTCONF uses to tag a default value. A member whose name starts with `@` is not a data node. ## Why this matters in practice The rule makes each node's JSON spelling deterministic: given the schema, exactly one name is valid at each position. That lets a server map JSON to XML and back, which RFC 7951 Section 3 notes requires the YANG model to be available, and it keeps two modules' identically named nodes apart. For a client it means the body must be built from the schema, not from the shape of the data alone.

  • What does the JSON body of a RESTCONF PUT to a single list entry look like?
    Its top-level member is the target node, qualified with its module even though the URI already names it, and a list entry is still an array with one object. RFC 8040's example `PUT` to one album sends `{"example-jukebox:album": [ {"name": ..., "year": ...} ]}`. The key values in the body must equal those in the URI; a PUT cannot change a list entry's keys.
  • Is it acceptable for a RESTCONF client to qualify every JSON member name with its module?
    No. RFC 7951 Section 4 says the qualified form MUST be used at the top level and where a node's namespace differs from its parent's, and the simple form MUST be used in all other cases. A server is entitled to reject `"example-net:mtu"` inside `"example-net:ports"`; over-qualifying is as non-conforming as under-qualifying.

A family tree written for strangers: the first ancestor's full surname is written out, the children inherit it unstated, and only someone who joined from another family gets their own surname written next to their name.

saying these in an interview costs you the question

  • Qualifying every JSON member name with its module is always safe
  • The JSON qualifier is the module's short YANG prefix, as in a when expression
  • Only the RESTCONF URI needs module names; the body is plain JSON
  • A YANG list with one entry can be sent as a bare JSON object
  • List keys must be the first members of a JSON list entry, as in XML
open as a page

Which media types carry YANG data in RESTCONF, and how do the Accept and Content-Type headers decide the encoding?

level: juniorimportance: should knowfreq 14%

basics

~20 s

RESTCONF carries YANG data as application/yang-data+json (RFC 7951 rules) or application/yang-data+xml. Content-Type names the encoding of the body sent, Accept the encoding wanted back; an unsupported input format earns 415, an unacceptable output format 406.

open as a page

Why does RFC 7951 encode a YANG uint64 counter as a JSON string, and an empty-type leaf as [null], in RESTCONF bodies?

level: middleimportance: should knowfreq 10%

basics

~20 s

Many JSON parsers store numbers as IEEE 754 doubles, exact only up to 2^53, so int64, uint64 and decimal64 travel as strings; and many treat a null member as missing, so an empty leaf is the one-element array [null].

open as a page

A RESTCONF JSON body sets the ietf-interfaces type leaf to plain ethernetCsmacd and is rejected; how must RFC 7951 encode identityref values?

level: seniorimportance: should knowfreq 7%

basics

~20 s

An identityref value is a string naming the identity, qualified module:identity with the defining module's name whenever the identity lives in a different module from the leaf, so ietf-interfaces' type takes "iana-if-type:ethernetCsmacd", not the bare name or an XML prefix.

open as a page

What does a RESTCONF ietf-restconf:errors response body contain, and how does the server choose its encoding?

level: seniorimportance: nice to knowfreq 8%

basics

~10 s

An ietf-restconf:errors body is a list of error entries, each with a mandatory error-type and error-tag plus optional error-app-tag, error-path, error-message and error-info; it is encoded as Accept asks, else like the request.

open as a page