What's changed: Initial version
6.2Constructing JSON and YANG
Teaches reading and writing JSON to the level of judging whether a document is valid (object {} vs. array [], no trailing comma, keys in double quotes, value-type distinctions), and then YANG as the language that defines data types and structure with container/list/leaf, understood as the benefit of model-driven operations.
Once you exchange payloads with RESTCONF or a controller API, an invalid JSON body is rejected before it ever reaches the device. What this section builds is not an explanation of "what JSON is" but the ability to judge a presented fragment valid or invalid on sight and repair it character by character. And where JSON is the container for data, YANG is the type definition stating what belongs in it. Blurring the two as "both about data" produces the misconception that "JSON can enforce types"—in reality YANG guarantees type and structure, and that guarantee is what makes consistent, cross-vendor automation possible.
6.2.1Rules for a valid JSON document
- An object uses braces
{}to list key/value pairs; an array uses brackets[]to list values in order. They nest, and the standard shape is "an array inside an object, objects inside the array," as in{"interfaces": [{"name": "Gi1", "enabled": true}, {"name": "Gi2", "enabled": false}]}. A document is invalid unless the kind and count of opening and closing brackets match, and closing a{with a]is a common break. - Keys must always be wrapped in double quotes (
{"name": "Gi1"}is valid;{name: "Gi1"}is not). JavaScript object literals and Python dictionaries permit unquoted keys and single quotes, but JSON accepts no single quotes at all—{'name': 'Gi1'}is invalid. This gap bites when a Pythondictis stringified and sent as-is, which is exactly why you pass it throughjson.dumps(). - No comma may follow the last element (a trailing comma is invalid).
{"a": 1, "b": 2,}and[1, 2, 3,]are syntax errors, and the parser rejects the whole document. This is the most frequent break in payloads edited by adding or removing lines, and the key point is that "one character in the editor means the entire document is invalid to the API." - Value types are distinct: strings carry double quotes (
"1500"), numbers do not (1500), booleans are lowercasetrue/false, and the empty value isnull.True/False(Python's capitalized form) andNoneare invalid in JSON, and since"1500"and1500are different types, sending a quoted value where a number is expected can be rejected as a type error.
6.2.2YANG: the language that defines the data model
- YANG is a language that defines the structure, types, and constraints of configuration and state data—it is neither data nor a transport protocol. Because NETCONF (carrying XML) and RESTCONF (carrying JSON or XML) share the same YANG model, "the model = what is handled" and "the protocol = how it is carried" stay cleanly separated. That separation is the heart of model-driven programmability.
- A container is a holder that groups related items (a single instance, mapping to a JSON object); a list is a collection of multiple same-kind entries that carries a key (identifier) (mapping to a JSON array—for example, a set of interfaces identified by
name); and a leaf is a single, indivisible value carrying a type (string, uint32, boolean, and so on). These three words express nearly the entire hierarchy. - YANG's benefit is validation up front through types and constraints. Given
leaf mtu { type uint32; }, a value such as"mtu": "large"is rejected as a model violation before it is ever applied to the device, preventing CLI typos from reaching production. Moreover, using standard models (IETF, OpenConfig) absorbs vendor differences, reducing the need to write per-device CLI syntax.
You can judge JSON validity with a four-point check: (1) bracket matching (kind and count of {} and []) -> (2) keys in double quotes (single-quoted or bare keys are invalid) -> (3) no trailing comma -> (4) value types (true/false/null lowercase, numbers unquoted). Read YANG with three words—container = a grouping holder, list = multiple keyed entries, leaf = a single typed value—and always separate the model (YANG) from the protocol (NETCONF/RESTCONF) as different layers.
Suppose you are asked why a script pushing interface configuration over RESTCONF is rejected with 400 Bad Request before reaching the device. The payload was { "ietf-interfaces:interface": { "name": "GigabitEthernet2", "description": 'uplink to core', "enabled": True, "mtu": "1500", } }. Suspecting the device's RESTCONF configuration is the long way around—this payload is invalid or inappropriate in four places. First, the description value is wrapped in single quotes; JSON expresses strings only with double quotes, so this alone is a syntax error. Second, the enabled value is capitalized True. That is Python's boolean spelling, whereas JSON booleans must be lowercase true/false (and likewise null, not None). These two typically arise from stringifying a Python dict with str() and sending it as-is, and passing it through json.dumps() corrects both automatically—the practical fix that prevents recurrence. Third, "mtu": "1500" is syntactically valid but inappropriate as a type. If the YANG model defines leaf mtu { type uint32; }, what is expected is the unquoted number 1500, and the string "1500" can be rejected as a model violation—the core insight for this family of items is that "parses as JSON" and "conforms to the model" are two separate gates. Fourth, there is a trailing comma after "mtu", which by itself makes the parser reject the whole document. The correct repair is therefore { "ietf-interfaces:interface": { "name": "GigabitEthernet2", "description": "uplink to core", "enabled": true, "mtu": 1500 } }. Looking a level deeper, YANG also explains why the structure looks like this: ietf-interfaces:interface is a container-like holder grouping one interface's attributes, and name, description, enabled, and mtu within it are leafs, each carrying a type. To send several interfaces at once you would express a list keyed by name as a JSON array. Putting an object where an array belongs, or an array where an object belongs, yields a document that is valid JSON yet rejected for violating the model—so being able to separate a syntax error from a model mismatch when a 400 arrives is the key to avoiding pointless device-side investigation.
| Aspect | Invalid or inappropriate example | Correct form | How it is rejected |
|---|---|---|---|
| Key quoting | `{name: "Gi1"}` / `{'name': "Gi1"}` | `{"name": "Gi1"}` | Syntax error (whole document rejected) |
| Trailing comma | `{"a": 1, "b": 2,}` | `{"a": 1, "b": 2}` | Syntax error (whole document rejected) |
| Booleans and null | `"enabled": True` / `"vrf": None` | `"enabled": true` / `"vrf": null` | Syntax error (undefined token) |
| Numeric type | `"mtu": "1500"` (YANG says `uint32`) | `"mtu": 1500` | Parses as JSON but rejected as a model violation |
| Structural mapping | An object placed where a `list` (multiple) belongs | Express it as an array `[{...}, {...}]` | Parses as JSON but rejected as a model violation |
Trap: "JSON also allows single-quoted keys / tolerates a trailing comma" is wrong—both are syntax errors that reject the whole document (easily confused with Python dict notation, hence json.dumps()). Also wrong: "YANG is a data transport protocol"—YANG is a language defining the model (types and structure), while NETCONF (XML) and RESTCONF (JSON/XML) do the carrying. And "valid JSON is always accepted by the device" is wrong—syntactic validity and model conformance are separate gates, and a type mismatch such as "mtu": "1500" can be rejected as a model violation.
6.2.3Section summary
- Valid JSON satisfies matched brackets, double-quoted keys, no trailing comma, and lowercase
true/false/null; single quotes and trailing commas reject the entire document - YANG is a language defining the model (types and structure): container = grouping holder, list = multiple keyed entries, leaf = a single typed value; NETCONF/RESTCONF do the carrying
- On a
400, separate syntax error from model mismatch—type mismatches ("1500"vs.1500) and structural ones (object vs. array) are rejected even though the JSON is valid
Sign in to track progress — Log in.
Quick check
(just a quick review)Q1. A script pushing interface configuration over RESTCONF is rejected with 400 Bad Request before reaching the device. The payload sent is `{ "ietf-interfaces:interface": { "name": "GigabitEthernet2", "enabled": True, "mtu": 1500, } }`. What should be corrected first?
Q2. A colleague says, "Since YANG can transfer configuration data to devices, NETCONF and RESTCONF become unnecessary." What is the most appropriate correction?
Q3. You want to configure several interfaces in a single request. In the YANG model, interfaces are defined as a `list` keyed by `name`. Which JSON payload structure is most appropriate?
Keep track of your progress
The full study guide is free to read. Sign up free to practice with the question bank, track what you have read, review your mistakes, and highlight passages.

