Interpret JSON Encoded Data

In this blog post, we will discuss the JavaScript Object Notation (JSON) data format. The target audience is CCNA and CCNP candidates preparing for the exams.

Interpret JSON Encoded Data

The content provides fundamental overview of the following topics:

CCNA exam

6.7 Interpret JSON encoded data

CCNP ENCOR exam

6.2 Construct valid JSON encoded file

JSON Overview

JSON is an open standard text-based file format to store and exchange serialized data. Serialization is the process of converting an object into a format that can be stored or transported to later recreate it.

JSON was originally derived from JavaScript, however, many other programming languages can interpret and generate JSON data. Figure 1 shows how JSON components fit together.

JSON text can represent one of the following values (orange and blue circles):

  • String
  • Number
  • Literal name (false, true, null)
  • Array
  • Object
Figure 1. JSON Values, Objects and Arrays
Figure 1. JSON Values, Objects and Arrays

JSON simple values

Strings, numbers, and literals

The simple values can represent some text or number and cannot contain other values. For example, below are examples of valid JSON texts:

Listing 1

"I'm a JSON"
100
true
null

As per RFC 8259, JSON text can be represented by any serialized value. Some specifications of JSON require that valid JSON text must be an object or an array.

Note that the string values must be enclosed in quotation marks.

JSON structured data values

Structural characters

JSON values that represent structured data (blue circles) created using 6 structural characters listed below:

  • Square brackets [] – beginning and end of an array
  • Curly brackets {} – beginning and end of an object
  • Colon : – Name separator
  • Comma , – Value separator

JSON allows the use of whitespaces, such as spaces, tabs, and new lines to format the text for readability. Contrasted to Python, indentation is used only for readability.

Array

An array contains zero or multiple ordered elements. Elements don’t have to be of the same type.

Listing 2

[ "abc", 23, null ]

Object

An object contains zero or multiple members, separated by commas. Each member is in the name: value format. Name must be unique within an object.

Listing 3

{ 
    "address": "192.168.8.1", 
    "mask": "255.255.255.255" 
}

Nested Objects and Arrays

Arrays and objects can contain both simple values, other arrays, and other objects.

For instance, below is the object, as we can see it starts with an opening curly brace. The object contains 2 members with name tags of “primary_address” and “secondary_address”. Each of the member’s value is another object that consists of 2 more members, named “address” and “mask”.

Listing 4

{ 
    "primary_address": 
    {
        "address": "192.168.8.1", 
        "mask": "255.255.255.255"
    },
    "secondary_address": 
    {
        "address": "192.168.9.1", 
        "mask": "255.255.255.255"
    },
}

Let’s create an array that will contain 2 objects representing addresses. The opening square bracket starts the definition of an array. Then we wrap each of the members from the previous example into curly brackets to create an object, as array stores elements – not members consisting of name: value pairs.

Listing 5

[ 
    {
        "primary_address": 
        {
            "address": "192.168.8.1", 
            "mask": "255.255.255.255"
        }
    },
        "secondary_address": 
        {
            "address": "192.168.9.1", 
            "mask": "255.255.255.255"
        },
    }
]

How to interpret JSON encoded data

In one of the previous blog posts dedicated to REST API, we’ve programmatically extracted a JSON representation of an interface from the IOS-XE router. This listing below shows several router’s interfaces, so we can have some arrays in the example.

Listing 6

{
  "Cisco-IOS-XE-native:interface": {
    "GigabitEthernet": [
      {
        "name": "1",
        "ip": {
          "address": {
            "primary": {
              "address": "192.168.7.4",
              "mask": "255.255.255.0"
            }
          }
        },
        "mop": {
          "enabled": false,
          "sysid": false
        },
        "Cisco-IOS-XE-ethernet:negotiation": {
          "auto": true
        }
      },
      {
        "name": "2",
        "shutdown": [
          null
        ],
        "mop": {
          "enabled": false,
          "sysid": false
        },
        "Cisco-IOS-XE-ethernet:negotiation": {
          "auto": true
        }
      }
    ]
  }
}

Let’s interpret this document. Figure 2 shows the structure of the JSON code from the example above.

The top-level object (#1) has a single member with the name of “Cisco-IOS-XE-native:interface”. This member’s value is another object (#2).

The object #2 also has a single member named “GigabitEthernet”, whose value is an array (#3).

Array contains 2 elements – object #4 and object #5.

Object #4 has 4 members, with the following names:

  • “name”
  • “ip”
  • “mop”
  • “Cisco-IOS-XE-ethernet:negotiation”

Member called “name” has a string value of “1”. The next member named “ip” has an object (#6) as a value. Object #6 has a single member with the name of “address” having another object (#7) as a value.

The pattern of finding array elements and object members should be apparent by now.

Figure 2. Cisco IOS-XE RESTCONF JSON interpretation example
Figure 2. Cisco IOS-XE RESTCONF JSON interpretation example

How to construct JSON encoded data

Online Tools

The easiest way to create a JSON encoded data is to use one of the available online JSON editors. For example, one is available via this URL. It automatically checks JSON file syntax, which can be useful to find a missing bracket. The other feature of this tool is the ability to auto-format code into a compact format or full format (with line breaks and indentation, as shown in the previous example).

The screenshot of the tool with JSON text from the previous example is shown below.

Figure 3. JSON Editor Online
Figure 3. JSON Editor Online

Python Collections Overview

To continue with the following examples, we recommend checking this article (URL) for a brief quick start and Python installation instructions.

Let’s discuss several Python fundamental topics before proceeding with the practical examples.

  • Data Structures: lists and dictionaries

Lists and dictionaries are examples of collections in Python. Python’s JSON module maps lists to JSON arrays, and dictionaries to JSON objects.

The syntax is identical between matching pairs of data structures, as shown in Figure 4.

Figure 4. Mapping of JSON structured data to Python collections
Figure 4. Mapping of JSON structured data to Python collections

The listing below shows an example of a list and a dictionary definition in Python.

A list is defined in Python using square brackets. Python uses None instead of null literal in JSON.

The dictionary is wrapped with curly brackets and has familiar from JSON example syntax. JSON’s name tag (value just before the colon) corresponds to a dictionary key in Python. It is followed by a colon and a value, which is in our example a string.

Listing 7

sample_list = [ "abc", 23, None ]
sample_dictionary = { "address": "192.168.8.1", "mask": "255.255.255.255" }

Let start interactive Python prompt to demonstrate how to work with lists and dictionaries.

Listing 8

c:\PythonExamples>python
Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:20:19) [MSC v.1925 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> sample_list = [ "abc", 23, None ]
>>> sample_dictionary = { "address": "192.168.8.1", "mask": "255.255.255.255" }

Both lists and dictionaries can be passed to print() method, which will display their string representation.

Listing 9

>>> print(sample_list)
['abc', 23, None]
>>> print(sample_dictionary)
{'address': '192.168.8.1', 'mask': '255.255.255.255'}

We can access individual elements in a list using their index position.

Listing 10

>>> print(sample_list[0])
abc
>>> print(sample_list[1])
23

To extract values for a specific dictionary key, we can use the key’s name as an index.

Listing 11

>>> print(sample_dictionary["address"])
192.168.8.1
>>> print(sample_dictionary["mask"])
255.255.255.255
  • Working with files

We will save and read JSON files to and from a file saved on the disk in the next examples.

To open a file for read access in Python the following code is used:

Listing 12

with open("json_test.json","r") as json_file:
    … some code that makes use of json_file

To open the same file for write access, use “w” instead of “r” as a parameter for the open() function. Use of keyword “with” ensures that the file is properly closed after the use.

Decoding JSON in Python example

Python module called json provides JSON encoding and decoding capabilities. There are 2 methods performing these functions:

  • dumps – Python data structure to JSON text
  • loads – JSON text into Python data structure

Let’s create a text file containing JSON text from Listing 6 and save it as json_ios_xe.json.

As the next step, we will create a file named json_example.py that will have the following Python code in it.

Listing 13

import json

with open("json_ios_xe_interfaces.json", "r") as json_file:
    json_file_content = json_file.read()
decoded_json = json.loads(json_file_content)

print(decoded_json)
print()
print(type(decoded_json))

Line #1 imports json module, so we can use its feature in our code.

The code in line #3 opens our file for read-only access. The access to the file content is provided via json_file variable. The code in line #4 reads-in content of the file into a string variable.

Line #5 uses json.loads() function to read the string representation of JSON text. The returned value is assigned to the decoded_json variable. As the JSON text is a JSON object, the decoded_json object will be a Python dictionary.

Line #7 prints the Python dictionary, followed by an empty line created by line #8. Finally, line #9 prints out the type of decoded_json object, so we can validate that it is in fact a Python dictionary.

Let’s run the code and see the result.

Listing 14

c:\PythonExamples>python json_example.py
{'Cisco-IOS-XE-native:interface': {'GigabitEthernet': [{'name': '1', 'ip': {'address': {'primary': {'address': '192.168.7.4', 'mask': '255.255.255.0'}}}, 'mop': {'enabled': False, 'sysid': False}, 'Cisco-IOS-XE-ethernet:negotiation': {'auto': True}}, {'name': '2', 'shutdown': [None], 'mop': {'enabled': False, 'sysid': False}, 'Cisco-IOS-XE-ethernet:negotiation': {'auto': True}}]}}

<class 'dict'>

Encoding to JSON in Python example

In this example, we will use the dictionary created in the previous example, change the IP address to “192.168.7.5” and will encode it as another JSON file.

The first task is to identify the full path to the IP address. We have several nested layers of hierarchy within the outer-most dictionary. To access inner dictionaries and lists we will append [<index_or_key_name>] to the parent identifier.

Full path to value of ‘address’ key will be:

Listing 15

decoded_json['Cisco-IOS-XE-native:interface']['GigabitEthernet'][0]['ip']['address']['primary']['address']

In the example above the index of [0] is used, as the ‘GigabitEthernet’ key has the value of a list and we are interested in the first element.

Below is the full listing of a program code that changes the IP address and saves it as a new JSON file on the disk.

Listing 16

import json

with open("json_ios_xe.json", "r") as json_file:
    json_file_content = json_file.read()

decoded_json = json.loads(json_file_content)

decoded_json['Cisco-IOS-XE-native:interface']['GigabitEthernet'][0]['ip']['address']['primary']['address'] = \
    "192.168.7.5"

encoded_json_compact = json.dumps(decoded_json)
encoded_json_indented = json.dumps(decoded_json, indent = 4)

with open("json_ios_xe_compact.json", "w") as json_file:
    json_file.write(encoded_json_compact)

with open("json_ios_xe_indented.json", "w") as json_file:
    json_file.write(encoded_json_indented)

Line #8 sets the value to a new IP address. Lines #11 and #12 create a string containing JSON text, it passes our modified dictionary called decoded_json to json.dumps() function. The example demonstrates that the named parameter called “indent” can be passed to the dumps() method to perform the formatting of the JSON file.

Line #15 and #18 saving the resulted text to files on the disk.

Let’s run the code and see the result.

Listing 17

c:\PythonExamples>python json_example.py

Two new files are created in c:\PythonExamples folder, as shown in the screenshot below.

Figure 5. JSON text decoded by Python's json.dumps()
Figure 5. JSON text decoded by Python’s json.dumps()

Self-Test Questions

List 6 types of value types that JSON text can represent?
String, number, Boolean (false, true), null, array, and object.
Describe JSON array and the process of defining one.
A JSON array contains ordered elements and defined using square brackets. For example, [ “abc”, 23, null ]
Describe JSON object and the process of defining one.
A JSON object contains members separated by a comma. Each member has a name and value separated by a colon. It is defined using curly brackets. For example, { “address”: “192.168.8.1”, “mask”: “255.255.255.255” }
Name Python types that are mapped to JSON's array and object
Python’s list maps to JSON array, and Python’s dictionary maps to a JSON object
What Python's module is responsible for encoding and decoding of JSON-formatted data?
json module. To decode use json.loads() and to encode – json.dumps().

Interpret Basic Python Components and Scripts

In this blog post, we will provide an introduction to Python components and scripts in the context of Cisco certification. We will show how to get started with Python and explain the most commonly used elements of Python scripts – variables, functions, program flow, conditional logic, and “for” loops.

Interpret Basic Python Components and Scripts

The content aims to help CCNP/CCIE Enterprise track candidates to prepare for the ENCOR exam, which includes the following topic:

6.1 Interpret basic Python components and scripts

Many CCNP tracks have automation sections that assume some knowledge of Python. DevNet track expects more extensive knowledge in Python.

Python Installation

Python is an interpreted language, which means that the code of a program is not pre-compiled into an executable that contains machine instructions. Python code can be opened and edited with any text editor. Python programs have a .py extension.

To run a Python code an interpreter is required. It reads the code and converts it into machine instructions.

Python is available for different platforms. Python 3.x is the recommended version and we will use it in our examples.

To download Python installation files navigate to this URL. Start the installer.

We use Windows 10 in our examples. Enable the checkbox “Add Python 3.x to PATH” and press Install Now.

Figure 1. Python Installation Options
Figure 1. Python Installation Options

Start Windows CLI utility by starting typing “Command Prompt”. Once started type in the following command to confirm that Python interpreter is available.

Microsoft Windows [Version 10.0.18362.836]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\PythonExamples>python --version
Python 3.8.3

Keep the command prompt window opened.

Hello World!

We will start with a simple “Hello World!” example.

Open a text editor, such as Notepad, and type-in the following code:

print("Hello World!")

The example uses a built-in print() function that displays a message on the screen.

Save the file as hello_world.py in a folder on your computer. To run the program, we will pass the full file name to python interpreter:

C:\PythonExamples>python c:\PythonExamples\hello_world.py
Hello World!

Variables

A variable stores some value, which can be accessed in the code by using its name. In Python, variables are not declared and can be used by assigning a value to them.

Let’s add a few more lines to the hello_world file. The new code creates a line number variable that is changed after each use. First two times it was statically set to 2 and 3, and in the line, before the last, we’ve just incremented its value by 1. The print function is being provided with 2 arguments – descriptive text and the line number variable.

print("Hello World!")
line_number = 2
print("This is the line number", line_number)
line_number = 3
print("This is the line number", line_number)
line_number = line_number + 1
print("This is the line number", line_number)

When the program is launched the following output is displayed on the screen.

C:\PythonExamples>python c:\PythonExamples\hello_world.py
Hello World!
This is the line number 2
This is the line number 3
This is the line number 4

Functions

A function minimizes the amount of duplicate code. It can also provide better structure and improve the readability of program code, by wrapping related logic under the function definition, which can be called by a descriptive name from other places of the program.

Let’s adjust our program to demonstrate the use of functions.

def line_number_printer(number):
    print("This is the line number", number)

def calculate_next_line_number(previous_number):
    return previous_number + 1

print("Hello World!")
line_number = 2
line_number_printer(line_number)
line_number = calculate_next_line_number(line_number)
line_number_printer(line_number)
line_number = calculate_next_line_number(line_number)
line_number_printer(line_number)

The program produces exactly the same output as the code in the previous example.

We have introduced 2 functions:

  • line_number_printer(number)
  • calculate_next_line_number(previous_number)

Figure 2 shows how the functions are defined and used in the example above. Not all lines from the example are shown for brevity.

Figure 2. Python Functions Example
Figure 2. Python Functions Example

Let’s go through the diagram and discuss each element:

  1. A function’s definition must precede its use. The code within the definition is not executed unless it is called.
  2. Function definition starts with a keyword “def”.
  3. The function name should be in lower case with underscore used as a word separator. Python’s style guide is called PEP 8. It explains different elements of style, such as the naming convention and how the code must be formatted (https://www.python.org/dev/peps/pep-0008).
  4. A function can accept a value as an input in the form of parameter. Variable name in parentheses stores value supplied when the function was called. This variable is available for use within the function body.
  5. The line containing function definition ends with a colon showing that function statements will follow in the next lines.
  6. The code statements within a function are indented. PEP 8 recommends the use of spaces for indentation instead of tabs. Also, 4 spaces should separate each indentation level.
  7. A function can be invoked to perform some action without returning any values to the caller. It can also return a value; such as a result of a calculation or a success code back to the caller. To create such a function, a statement starting with keyword return is used. When this statement is encountered, function execution stops.

Conditional Logic

Conditional logic statements allow us to perform certain actions based on an evaluation result of a condition. Let’s modify our example, so the line_number_print function displays different strings depending on whether the number is odd or even. The listing below shows the modifications made, the remaining code is not changed.

def line_number_printer(number):
    if number % 2 == 0:
        print("This is the line number", number, "and it is even")
    else:
        print("This is the line number", number, "and it is odd")

When the program is launched the following output is displayed on the screen.

C:\PythonExamples\>python c:\PythonExamples\hello_world.py
Hello World!
This is the line number 2 and it is even
This is the line number 3 and it is odd
This is the line number 4 and it is even

Figure 3 shows how conditional logic is used in the example above.

Figure 3. Python Conditional Logic Example
Figure 3. Python Conditional Logic Example

Let’s go through the diagram and discuss each element:

  1. “if” keyword is followed by a logical test that can be either True or False.
  2. If the test is evaluated as True, the statement (or multiple statements) under the “if” section is executed.
  3. As with the functions, the body of “if” or “else” sections comprises of indented statements.
  4. If the test is evaluated as False, the statement (or multiple statements) under the “else” section is executed.

for Loops

The “for” loops can be used to apply an action to each element of a collection. For example, we can store a list of switch interfaces in a list. To check the status of each of these interfaces we can use the “for” loop to iterate through the list and then run a command against each of the interfaces.

Let’s rewrite our program using “for” loops to automatically assign line numbers.

The listing below shows the complete code, as we removed the line calculation function and multiple calls to print function.

def line_number_printer(number):
    if number % 2 == 0:
        print("This is the line number", number, "and it is even")
    else:
        print("This is the line number", number, "and it is odd")

print("Hello World!")
for line_number in range(2, 5):
    line_number_printer(line_number)

When the program is launched the same output is displayed on the screen.

C:\PythonExamples>python c:\PythonExamples\hello_world.py
Hello World!
This is the line number 2 and it is even
This is the line number 3 and it is odd
This is the line number 4 and it is even

Figure 4 shows how “for” loop is used in the example above.

Figure 4. Python "for" loop Example
Figure 4. Python “for” loop Example

Let’s go through the diagram and discuss each element:

  1. “for” keyword is followed by a variable name that will be changing its value on each pass.
  2. “in” keyword is followed by a list of values that will be assigned one at a time to the “for” variable on each iteration.
  3. Statements that perform actual work during each cycle are indented under the “for” loop.

Not shown in the example, “break” keyword stops loop processing and continues with the code following the loop. Similarly, the “continue” keyword stops the current pass processing, but in contrast to “break”, it starts the next cycle of the loop.

Self-Test Tasks:

Task 1

Write a function that accepts a number and prints it out followed by “is the number passed as a parameter”.

Task 2

Write a function that accepts a number and prints out “Greater than 10” or “Less or equal than 10” depending on the number that was provided. The greater operator is “>” and less or equal is “<=”.

Task 3

Write a “for” loop that iterates over a list of interfaces Ethernet1/1, Ethernet1/2, and Ethernet1/3 and prints out the output below. To supply interfaces for “for” loop, use a list [ “Ethernet1/1”, “Ethernet1/2”, “Ethernet1/3” ]

interface Ethernet1/1
 description Added by Automation Script
 no shutdown
interface Ethernet1/2
 description Added by Automation Script
 no shutdown
interface Ethernet1/3
 description Added by Automation Script
 no shutdown

Self-Test Answers:

Task 1

def print_number(number):
    print(number, "is the number passed as a parameter")

Task 2

def compare_number_to_ten(number):
    if number > 10:
        print("Greater than 10")
    else:
        print("Less or equal than 10")

Task 3

for interface_name in [ "Ethernet1/1", "Ethernet1/2", "Ethernet1/3" ]:
    print("interface", interface_name)
    print(" description Added by Automation Script")
    print(" no shutdown")