First, the essential ideas
- JSON
- JavaScript Object Notation is a text format for exchanging structured data. It is language-independent data, not a program to execute and not a network transport protocol.
- Object and member
- A JSON object uses braces and contains name/value members. Names are strings in double quotes. Member order should not carry application meaning; use unique names for interoperable data.
- Array and index
- An array uses square brackets and preserves an ordered sequence of values. Python indexes the first value at zero. An array's values can themselves be objects or arrays.
- Scalar types
- JSON scalar values include strings, numbers, booleans and null. The boolean false is not the string "false"; the number 1500 is not the string "1500".
- Parser and serializer
- A parser turns JSON text into a language's data structures. A serializer turns those structures back into JSON text with correct escaping and type representation.
- Schema and meaning
- A schema or data model defines required fields, types and constraints beyond JSON syntax. Valid JSON can still be invalid for an API or misrepresent real operational state.
- Null and absence
- JSON null is an explicit value whose meaning is defined by the application. An absent member is not automatically equivalent to a member present with null.
Read outside in. Identify the root container, locate a named member, then follow any array position before reading a value. At the final value, ask both what it says and what type it is. That last question prevents a surprisingly common automation error.
See the idea
Follow the structure to the boolean
Select the root member, then the array item, then the nested field; check the final value's type.
Select the named member
The root is an object. Its interfaces member contains an array, not a single interface field.
What this model leaves out: Edges show containment and data access, not cables or packets. This is the complete path to one field in a synthetic record, not a live device response.
Full visual explanation and references
The R57 root object contains an interfaces array. Array item zero is the Gi1 object, whose enabled member holds the boolean false.
Edges show containment and data access, not cables or packets. This is the complete path to one field in a synthetic record, not a live device response.
- Select the named member
The root is an object. Its interfaces member contains an array, not a single interface field.
www.rfc-editor.org - Select the array item
Index zero selects the first object in this one-item fixture. Real inventories need a documented identity lookup.
www.rfc-editor.org - Check value and type
The enabled member is boolean false. Replacing it with the string "false" preserves valid JSON but violates this fixture's type contract.
www.rfc-editor.orgwww.rfc-editor.org
One idea at a time
Start with something familiar.
The example root is an object. Its interfaces member is an array. The first array item is another object containing name, enabled and mtu. Draw those four levels before typing a Python expression; the brackets will then describe a path rather than a puzzle.
Why learn this?
Automation needs predictable values. A string containing the word false can be treated as true by careless Python truth testing, which is very different from the boolean false. A syntactically valid payload can therefore cause an incorrect decision.
An everyday comparison
A filing cabinet holds labeled folders, and one folder holds an ordered set of forms. Each form has named boxes such as name, permission and capacity. Finding the right box requires following both labels and positions.
What happens in a network
Objects resemble named folders or forms, while arrays resemble ordered sets. Reading interfaces, then item zero, then enabled reaches one specific value without relying on the order of unrelated object members.
Where the comparison stopsA JSON document is not a physical cabinet and its types have exact rules. A checkbox value, a word saying false and an empty box are different representations whose meanings depend on the model.
Follow one worked example
- Parse the complete text.
json.loads converts the root to a Python dictionary, the array to a list, false to False and null to None.
Why: A parser handles structure and escapes; splitting the text on commas cannot handle general nested data.
- Navigate and inspect the final type.
data['interfaces'][0]['enabled'] reaches the first interface's boolean. Index zero selects an array item, not the first object key.
Why: Correct navigation and correct typing are distinct checks.
- Break syntax and then type separately.
A trailing comma raises a parsing error. A quoted false parses, but a boolean-type check rejects it. Restore the original value and retest.
Why: Each failure belongs to a different validation layer and requires a different repair.
Your first small task
Classify these JSON values: false, "false", 1500, "1500", null, [] and {}. Then explain whether the string "192.0.2.57" is automatically validated as an IPv4 address by a JSON parser.
Show a hint
Quotation marks change the type. JSON grammar does not know the operational meaning of a field called address.
Check the expected result
They are boolean, string, number, string, null, array and object. An address-shaped string remains a string; a separate address validator is needed.
Pause and explain it in your own words
Why is parsing success insufficient for an interface configuration payload?
Show a hint
Consider required fields, allowed types, platform constraints and observed device state.
Show the explanation
The parser checks the text's structure. The API model must also accept its fields and types, and the device must apply the intended change. Operational verification is a separate final step.
Short answer
What should you understand today?
JSON represents objects, arrays, strings, numbers, booleans and null. Parse it with a proper library, navigate the structure and validate expected types. Correct punctuation alone is not enough: "false" is a string, false is a boolean, and neither synthetic value proves a real interface's operating state.
Before you begin
Learning targets
- Review HTTP representations and the difference between configuration and operational evidence.
- Use an offline Ubuntu 24.04 VM with Python 3.12, or explicitly hand-trace the worksheet.
- No network account, device credentials, third-party package or paid API is required.
- Recognize JSON containers, scalar types, quoting and nesting.
- Navigate an object member and ordered array without assuming object key order.
- Use a parser, inspect types and separate syntax validation from domain validation.
- Repair a trailing-comma fault and a string-versus-boolean fault, then retest the original data.
Words you will meet
Open a word when you need its meaning. You do not need to memorize the whole list before reading.
JSON
JavaScript Object Notation is a text format for exchanging structured data. It is language-independent data, not a program to execute and not a network transport protocol.
Object and member
A JSON object uses braces and contains name/value members. Names are strings in double quotes. Member order should not carry application meaning; use unique names for interoperable data.
Array and index
An array uses square brackets and preserves an ordered sequence of values. Python indexes the first value at zero. An array's values can themselves be objects or arrays.
Scalar types
JSON scalar values include strings, numbers, booleans and null. The boolean false is not the string "false"; the number 1500 is not the string "1500".
Parser and serializer
A parser turns JSON text into a language's data structures. A serializer turns those structures back into JSON text with correct escaping and type representation.
Schema and meaning
A schema or data model defines required fields, types and constraints beyond JSON syntax. Valid JSON can still be invalid for an API or misrepresent real operational state.
Null and absence
JSON null is an explicit value whose meaning is defined by the application. An absent member is not automatically equivalent to a member present with null.
Recognize the six value categories
JSON has objects and arrays as structured values, plus strings, numbers, booleans and null. Object names and strings use double quotes; booleans and null are lowercase unquoted literals. Colons separate names from values and commas separate members or array items. Standard JSON does not permit comments or a trailing comma. A top-level JSON value need not always be an object, although many network APIs use objects.
- Use a parser rather than evaluating JSON as program code.
- Keep exact types when transferring values between languages.
Follow a nested path deliberately
An object is accessed by member name; an array is accessed by position or by searching its items for a desired field. Object key order is not a reliable semantic contract. Array order is significant, but an API may not promise that a particular interface will always be first. Our one-item fixture deliberately fixes item zero so a beginner can learn the mechanics before handling real inventories.
- Check the container type before choosing name access or index access.
- A missing key or empty array needs explicit handling, not a guessed default.
Parsing does not validate the network model
A JSON parser can accept an object with unknown fields, a wrong type or an impossible network value. A schema or API model supplies additional requirements. YANG-modeled JSON has its own encoding rules, including module-qualified names and type-specific representations; do not generalize the synthetic worksheet into a Cisco RESTCONF payload. Some YANG numeric types are represented as strings, so follow the actual model rather than converting every digit string.
- Syntax, schema and operational truth are three separate validation levels.
- Do not silently coerce data when a wrong type should trigger investigation.
Handle null, duplicates and language differences
Null is an explicit JSON value; its meaning could be unknown, cleared or unavailable depending on the API. An omitted field may mean something else. Use unique object member names: duplicate names can be handled differently by parsers, and Python's default decoder keeps the last one. Also, Python defaults accept some nonstandard numeric values such as NaN; this worksheet uses ordinary finite values and serializes with allow_nan=False.
- Do not equate null with an empty string, zero or a missing member.
- A convenient parser's defaults are not a complete strict-schema validation policy.
Serialize checked structures instead of assembling text
A serializer escapes strings and writes valid JSON tokens for supported values. Build or change a parsed structure, validate the relevant fields, then serialize it. Avoid concatenating a user's value into JSON punctuation, which can introduce quoting or escaping defects. Pretty printing adds whitespace for readability without changing the underlying values. JSON text is not encrypted merely because a program generated it.
- Keep secrets out of fixtures, logs and public examples.
- Use UTF-8 for exchanged JSON and retain complete data rather than clipped examples.
Make the coverage and practical boundary explicit
The lesson addresses v1.1 6.7, interpreting JSON encoded data. It supports REST representations taught in Day 56 and automation workflows taught next. The announced v2.0 does not name the same standalone JSON objective, so its mapping is supporting knowledge, not a newly invented exam requirement. v1.1 remains current through 2 February 2027; v2.0 starts on 3 February.
- No Cisco runtime, controller query or API authentication is performed here.
- A deterministic authoring check is not independent review or observed learner execution.
Real-world walkthrough
A false-looking string produces a true decision
In a fictional inventory script, a spreadsheet export turns a boolean into the string "false". The JSON remains syntactically valid. A Python script uses a general truth test and treats the nonempty string as true, selecting an interface for a proposed action that should have been excluded.
- Preserve the synthetic reproduction and identify the exact nested field rather than changing unrelated parser settings.
- Compare the original boolean with the exported string using both value and type inspection.
- Confirm that parsing accepts both but the expected boolean contract rejects the string.
- Repair the upstream export or explicitly reject wrong types; do not infer boolean meaning from arbitrary strings.
- Retest true, false and wrong-type cases before connecting the script to any authorized device workflow.
Guided GNS3 lab
Parse, fault and restore a synthetic interface record
Navigate complete JSON and distinguish a parser error from a valid but wrong type. All variables stay in one offline Python session; no network endpoint or device is contacted.
Addressing plan
| Device | Interface | Address | Purpose |
|---|---|---|---|
| Worksheet VM | External NIC | Disconnected; no lab IP required | Keeps the parser exercise offline. |
| R57 record | Gi1 data field | No IP field is configured | Synthetic name, enabled and MTU values only. |
Set up the lab
- Open Terminal through the VM console and keep one interactive Python session for all steps.
- Use the complete supplied synthetic record; do not paste real configurations, tokens or personal data.
- Type each expression at the correct prompt. After an expected JSONDecodeError or AssertionError, the interactive interpreter remains usable.
- The paper alternative predicts each value and error category without claiming execution.
Start the parser session
In the Ubuntu VM console, open Terminal, record the Python version and start interactive Python. No package installation or network access is needed for the standard json module.
python3 --version
python3
import jsonWhat each command means
python3 --version- Record the available Python version.
python3- Enter the interactive interpreter.
import json- Load Python's standard JSON parser and serializer.
- What you should see
- Expect an interactive prompt and successful import; record actual results.
- Why this step matters
- Using a standard parser avoids teaching unsafe evaluation or fragile text splitting.
Parse the complete baseline
At the Python prompt in the same terminal console, store the complete JSON text and parse it. Single quotes delimit the surrounding Python string; the JSON member names inside remain double quoted.
raw = '{"device":"R57","interfaces":[{"name":"Gi1","enabled":false,"mtu":1500}],"note":null}'
data = json.loads(raw)
print(type(data).__name__, data['device'])What each command means
raw = '{"device":"R57","interfaces":[{"name":"Gi1","enabled":false,"mtu":1500}],"note":null}'- Store the original JSON text without changing its literals.
data = json.loads(raw)- Parse the text into Python data structures.
print(type(data).__name__, data['device'])- Check that the root is a dictionary and the device value is R57.
- What you should see
- Expect dict R57; the assignment itself does not print a result.
- Why this step matters
- The root's type determines how the next navigation step should work.
Navigate into the interface
At the same Python terminal console, inspect the array before selecting its first item. Then access the name, enabled and mtu members by their exact names.
print(type(data['interfaces']).__name__, len(data['interfaces']))
iface = data['interfaces'][0]
print(iface['name'], iface['enabled'], iface['mtu'])
print(data['note'] is None)What each command means
print(type(data['interfaces']).__name__, len(data['interfaces']))- Check for a list with one item in this controlled fixture.
iface = data['interfaces'][0]- Select the first array element using zero-based indexing.
print(iface['name'], iface['enabled'], iface['mtu'])- Display the three values from the nested object.
print(data['note'] is None)- Check the Python representation of the JSON null value.
- What you should see
- Expect list 1, then Gi1 False 1500, and True for the null mapping.
- Why this step matters
- Following containers explicitly makes a missing key or wrong level easier to diagnose.
Assert the expected local types
In the same Python terminal console, check this fixture's contract before any imagined network use. These assertions are specific to the worksheet, not a complete network API schema.
assert type(iface['enabled']) is bool
assert type(iface['mtu']) is int and iface['mtu'] == 1500
print('baseline types accepted')What each command means
assert type(iface['enabled']) is bool- Require a real boolean rather than a string or number.
assert type(iface['mtu']) is int and iface['mtu'] == 1500- Require this fixture's intended integer MTU value.
print('baseline types accepted')- Print a local checkpoint only after both assertions pass.
- What you should see
- Expect no assertion error and the checkpoint text; no device state is verified.
- Why this step matters
- Type checks catch defects that punctuation validation alone cannot detect.
Observe a syntax fault safely
At the same Python terminal console, parse a separate deliberately malformed string with a trailing comma. Do not overwrite raw or data. Read the error category, then continue at the next prompt.
broken = '{"device":"R57",}'
json.loads(broken)What each command means
broken = '{"device":"R57",}'- Create a bounded syntax fault in a separate text variable.
json.loads(broken)- Ask the parser to reject the invalid trailing comma.
- What you should see
- Expect JSONDecodeError; exact line and column wording may vary by version.
- Why this step matters
- A syntax error occurs before a useful data structure can be validated.
Restore parsing and introduce a type fault
At the same Python terminal console, reparse the untouched baseline first. Then replace only the local enabled value with the string false and inspect what Python truth testing does.
data = json.loads(raw)
iface = data['interfaces'][0]
iface['enabled'] = 'false'
print(type(iface['enabled']).__name__, bool(iface['enabled']))
assert type(iface['enabled']) is boolWhat each command means
data = json.loads(raw)- Restore the original parsed record from preserved text.
iface = data['interfaces'][0]- Rebind the interface reference to the restored object.
iface['enabled'] = 'false'- Introduce a valid JSON-representable string where the fixture expects a boolean.
print(type(iface['enabled']).__name__, bool(iface['enabled']))- Show that the value is a nonempty string and therefore truthy in Python.
assert type(iface['enabled']) is bool- Deliberately reject the wrong type with AssertionError.
- What you should see
- Expect str True followed by AssertionError; this is not a JSON syntax error.
- Why this step matters
- The controlled fault shows why generic truth testing must not replace a type contract.
Repair, serialize and retest
At the same Python terminal console, restore the boolean False, repeat both type checks and serialize the complete object. Parse it again to compare values rather than whitespace.
iface['enabled'] = False
assert type(iface['enabled']) is bool and iface['enabled'] is False
assert type(iface['mtu']) is int and iface['mtu'] == 1500
encoded = json.dumps(data, indent=2, allow_nan=False)
print(encoded)
assert json.loads(encoded) == json.loads(raw)What each command means
iface['enabled'] = False- Restore the intended boolean in Python.
assert type(iface['enabled']) is bool and iface['enabled'] is False- Verify both type and exact disabled value.
assert type(iface['mtu']) is int and iface['mtu'] == 1500- Confirm the unrelated MTU value was preserved.
encoded = json.dumps(data, indent=2, allow_nan=False)- Serialize checked values and reject nonfinite-number output.
print(encoded)- Display the full repaired JSON with lowercase false and null.
assert json.loads(encoded) == json.loads(raw)- Check round-trip equality with the complete original fixture.
- What you should see
- Expect complete serialized JSON and no final assertion errors.
- Why this step matters
- Restoration includes the unchanged fields and full value equality, not just one repaired display.
Close the disposable worksheet
At the same Python terminal console, summarize the syntax and type failures separately, then exit. Retain only synthetic notes; nothing was written to a device or sent over a network.
exit()What each command means
exit()- End the interpreter and discard the in-memory worksheet.
- What you should see
- Expect return to the shell with no network or filesystem configuration to undo.
- Why this step matters
- The evidence supports data interpretation only, so no device rollback or live-state claim is appropriate.
Verify
- Record Python version or label the exercise hand-traced.
- Verify the root object, array length, first object and exact member path.
- Distinguish the deliberate JSONDecodeError from the deliberate AssertionError.
- Confirm repaired enabled is a boolean False, not a string with that spelling.
- Require complete round-trip value equality and retain the explicit synthetic-data boundary.
Troubleshoot
- If a key lookup fails, inspect the current container and exact spelling; do not assume object order identifies the intended member.
- If the interpreter raises NameError, recreate the baseline in the same session before using dependent variables.
- If a trailing comma parses in another tool, determine whether it accepts a nonstandard extension; do not teach that as portable JSON.
- If duplicate keys or nonfinite values appear in real input, use an explicit strict-validation policy rather than trusting permissive parser defaults.
GNS3 does not provide Cisco images. A license or entitlement must permit the image in the selected environment; do not share or redistribute image files. Cisco Modeling Labs is an official alternative. Its supplied Cisco reference images are licensed for use within CML, not automatically for export to GNS3. An unlicensed learner must use the explicitly labeled paper alternative, not report simulated Cisco execution.
- Exit the interpreter; all exercise changes are in memory.
- Keep no real credentials or device exports in worksheet notes.
- For a future API workflow, validate its schema and permissions separately before any write.
Practice set
Answer before you reveal
01What is the difference between false and "false"?
Both can be syntactically valid JSON values, but they satisfy different schema requirements and behave differently in code.
02Does object member order identify an interface?
Array order is preserved, but real API inventories may still not promise that the intended interface is always first.
03What does a parser prove about an IPv4-looking string?
Domain validation such as address parsing and subnet membership belongs to another validation step.
04Why is null different from a missing member?
The model decides whether these mean unknown, clear, default or invalid. Do not silently substitute one for the other.
05Why avoid duplicate object names?
Unique names avoid ambiguity and make cross-language interpretation more predictable.
06Does the repaired record prove Gi1 is down?
Even a real configured disabled value would need context; operational status and live traffic are separate evidence.
Knowledge check
Quiz: prove the reasoning
Keep these
Technical takeaways
- Read JSON outside in through named members and ordered arrays.
- Quotes can change a value's type and therefore its behavior.
- Parsing, schema validation and operational verification are different checks.
- Treat null, absence and duplicates deliberately.
- Use parsers and serializers instead of evaluating or splitting data.
- Synthetic interface records are not live network evidence.
