Objective 6.7
Recognize components of JSON-encoded data
Why JSON matters
JSON (JavaScript Object Notation, pronounced “jay-son”) is the default data format for REST APIs, including every Cisco controller API. Almost any automation work involves reading JSON responses and writing JSON request bodies, and the exam will show you a JSON snippet and ask what it represents or what the value of a particular key is. JSON is also the language of the exam’s “recognize components” questions, so the vocabulary must be precise.
JSON is plain text, is language-independent (every programming language can read it), and is easy for both humans and machines to parse. It was derived from JavaScript object syntax but has nothing to do with running JavaScript.
The six JSON data types
| Type | Looks like | Rules |
|---|---|---|
| Object | { "key": value, "key2": value2 } |
Curly braces; an unordered collection of key/value pairs; keys are always strings in double quotes; pairs separated by commas |
| Array | [ value, value, value ] |
Square brackets; an ordered list of values; values separated by commas; values may be of mixed types |
| String | "GigabitEthernet1/0/1" |
Text in double quotes only; backslash escapes such as \" and \n |
| Number | 42, -7, 3.14, 1.5e3 |
No quotes; integers or decimals; no leading zeros; no hexadecimal |
| Boolean | true or false |
Lowercase, no quotes |
| null | null |
Lowercase, no quotes; represents “no value” |
Two of these, object and array, are containers that can hold any of the six types, including other objects and arrays. That is how JSON represents complex, nested information. The other four (string, number, boolean, null) are primitive values.
A first example
{
"hostname": "SW1",
"model": "C9300-48P",
"uptimeDays": 142,
"isReachable": true,
"lastError": null,
"vlans": [10, 20, 30]
}
Reading this out loud: it is an object (the outer braces) with six key/value pairs. "hostname" has the string value "SW1". "uptimeDays" has the number value 142 (no quotes). "isReachable" has the boolean value true. "lastError" has the value null. "vlans" has an array value containing three numbers.
Nesting
Values can be objects or arrays, and those can contain more objects and arrays, to any depth. This is how a list of interfaces, each with several properties, is represented.
{
"device": {
"hostname": "R1",
"mgmt": {
"ip": "10.0.0.1",
"mask": "255.255.255.0"
}
},
"interfaces": [
{
"name": "GigabitEthernet0/0",
"ip": "192.168.1.1",
"enabled": true,
"description": "LAN"
},
{
"name": "GigabitEthernet0/1",
"ip": "203.0.113.2",
"enabled": false,
"description": "WAN"
}
],
"ospf": {
"processId": 1,
"routerId": "1.1.1.1",
"areas": [0]
}
}
How to navigate this:
- The value of
deviceis an object. Inside it,hostnameis"R1"andmgmtis another object. - The value of
devicethenmgmtthenipis"10.0.0.1". Programmers write this path asdevice.mgmt.ipor, in Python,data["device"]["mgmt"]["ip"]. - The value of
interfacesis an array containing two objects. - Arrays are indexed starting at 0. So
interfaces[0]is the first interface object, andinterfaces[0].nameis"GigabitEthernet0/0".interfaces[1].enabledisfalse. ospf.areasis an array with a single number in it,[0]. Note that[0](an array containing zero) is different from0(a number).
More “what is the value” exercises
Study this Catalyst Center-style response and answer the questions that follow (answers are right below).
{
"response": [
{
"hostname": "CORE-SW1",
"managementIpAddress": "10.1.1.1",
"softwareVersion": "17.9.4",
"role": "CORE",
"upTime": "45 days, 3:12:08.00",
"interfaceCount": "54",
"errorCode": null,
"tags": []
},
{
"hostname": "ACCESS-SW7",
"managementIpAddress": "10.1.1.17",
"softwareVersion": "17.9.4",
"role": "ACCESS",
"upTime": "2 days, 17:05:44.00",
"interfaceCount": "26",
"errorCode": "SNMP_TIMEOUT",
"tags": ["floor2", "poe"]
}
],
"version": "1.0"
}
- What type of value is
response? An array (square brackets) containing two objects. - What is the value of
hostnamein the second object?"ACCESS-SW7". - What data type is the value of
interfaceCount? A string, because it is in double quotes ("54"), even though it looks like a number. This is a common trick. - What is
errorCodefor CORE-SW1?null. - How many elements are in
tagsfor CORE-SW1? Zero;[]is an empty array. - What is
tags[1]for ACCESS-SW7?"poe"(index 1 is the second element). - How many top-level keys does the outer object have? Two:
responseandversion.
JSON syntax rules and common errors
JSON is strict. A single mistake makes the whole document invalid, and a REST API will respond with 400 Bad Request. The rules and the mistakes that break them:
| Rule | Valid | Invalid (and why) |
|---|---|---|
| Keys must be strings in double quotes | {"name": "SW1"} |
{name: "SW1"} (unquoted key; legal in JavaScript, not in JSON) |
| Strings use double quotes only | {"name": "SW1"} |
{'name': 'SW1'} (single quotes are not JSON; Python prints dictionaries this way, which causes confusion) |
| No trailing comma after the last item | [10, 20, 30] |
[10, 20, 30,] (trailing comma) |
| Booleans and null are lowercase, unquoted | "up": true |
"up": True (Python style) or "up": "true" (that is a string, not a boolean) |
| Numbers are unquoted | "cost": 10 |
"cost": "10" is valid JSON but the value is a string, not a number |
| Every opening brace/bracket must be closed | {"a": [1, 2]} |
{"a": [1, 2} (mismatched) |
| Colon between key and value, comma between pairs | {"a": 1, "b": 2} |
{"a": 1 "b": 2} (missing comma) or {"a" = 1} (equals sign) |
| No comments | (none) | // comment or # comment inside JSON is invalid |
| Duplicate keys should be avoided | {"a": 1, "b": 2} |
{"a": 1, "a": 2} (behavior undefined; most parsers keep the last) |
Whitespace (spaces, tabs, newlines) between elements is ignored, so the following is exactly the same as the multi-line first example: {"hostname":"SW1","uptimeDays":142,"isReachable":true}. Indentation is only for human readability.
Key order inside an object is officially not significant. {"a": 1, "b": 2} and {"b": 2, "a": 1} carry the same information. Order inside an array is significant: [10, 20] and [20, 10] are different.
JSON compared with XML and YAML
| Feature | JSON | XML | YAML |
|---|---|---|---|
| Structure markers | {} and [] |
Opening and closing tags | Indentation and - |
| Quotes on strings | Required (double) | Not used | Optional |
| Comments | Not allowed | <!-- --> |
# |
| Data types | String, number, boolean, null, object, array | Everything is text unless a schema says otherwise | Same as JSON plus more |
| Main use | REST APIs | NETCONF, SOAP, older APIs | Ansible, config files |
| Verbosity | Medium | High | Low |