Software Development and Design · Topic 2 of 7
Parsing XML, JSON and YAML into Python
Learn how Python parses JSON, YAML and XML text into dictionaries and lists, and how to read nested values with the json, yaml and ElementTree modules.
- 4 min
json.loads()parses a string andjson.load()parses a file.json.dumps()turns Python data into a JSON string.- JSON objects become dictionaries and arrays become lists.
What it is
Parsing turns text in a data format into Python objects that your code can search and change.
Serialising is the reverse step. It turns Python objects back into text so you can send them or save them.
Once data is parsed, you work with ordinary dictionaries, lists, strings, numbers and booleans. You no longer think about braces or indentation.
How it works
Each format has a library, and each library maps the text onto Python types in a predictable way.
How JSON maps to Python
The built in json module needs no installation.
| JSON | Python |
|---|---|
| object | dict |
| array | list |
| string | str |
| number | int or float |
| true and false | True and False |
| null | None |
Four functions matter. json.loads() parses a string, and json.load() parses an open file.
json.dumps() makes a string, and json.dump() writes to a file. The trailing letter s stands for string. The indent argument makes the output easier to read, and sort_keys=True puts the keys in order.
import json
text = '{"hostname": "R1", "interfaces": [{"name": "Gi0/0", "ip": "10.0.0.1"}]}'
data = json.loads(text)
print(data["hostname"]) # R1
print(data["interfaces"][0]["ip"]) # 10.0.0.1
data["hostname"] = "R2"
print(json.dumps(data, indent=2))
You read a nested value by chaining keys and list positions. A missing key raises KeyError, and data.get("key") returns None instead.
Parsing YAML
YAML needs the third party PyYAML package, which you import as yaml. Install it with pip install pyyaml.
import yaml
with open("devices.yaml") as f:
devices = yaml.safe_load(f)
print(devices["interfaces"][0]["name"])
print(yaml.safe_dump(devices))
Use safe_load rather than load for data you did not write yourself. It builds only plain Python types and does not run code. Mappings become dictionaries and sequences become lists.
Parsing XML
Python has xml.etree.ElementTree in the standard library. It builds a tree of elements rather than a dictionary.
import xml.etree.ElementTree as ET
tree = ET.parse("devices.xml")
root = tree.getroot()
for device in root.findall("device"):
print(device.find("hostname").text)
print(device.attrib)
Each element has a tag, a text value and an attrib dictionary. Use find() for the first matching child and findall() for every match. ET.fromstring() parses a string instead of a file.
Many people prefer the third party xmltodict package. Its xmltodict.parse() function returns a dictionary, so you can use the same key lookups as with JSON.
Worked example with an API reply
The requests library has a shortcut. The response method .json() parses a JSON body into Python objects.
import os
import requests
BASE_URL = os.environ["API_BASE"] # scheme and host, set outside the script
resp = requests.get(BASE_URL + "/devices")
devices = resp.json()
for d in devices["items"]:
print(d["name"], d["status"])
Walking a parsed structure
Parsed data is often a dictionary that holds a list of dictionaries. A for loop visits each item in the list, and a key lookup picks the field you want.
for iface in data["interfaces"]:
if iface["ip"].startswith("10.0.0."):
print(iface["name"])
A common pattern is to loop, test a field, and collect the matches into a new list.
Parsing errors
A parser raises an error when the text is invalid.
json.JSONDecodeErrorfor bad JSON, such as single quotes or a trailing comma.yaml.YAMLErrorfor bad YAML, such as a tab used for indentation.ET.ParseErrorfor XML that is not well formed.
The function names tell you the input. loads and dumps work on strings, while load and dump work on file objects.
What to remember for the exam
Seven points are worth memorising.
json.loads()parses a string andjson.load()parses a file.json.dumps()turns Python data into a JSON string.- JSON objects become dictionaries and arrays become lists.
yaml.safe_load()reads YAML and needs the PyYAML package.xml.etree.ElementTreeparses XML into elements withtag,textandattrib.xmltodict.parse()turns XML into a dictionary.- A bad document raises a parsing error, and a missing key raises
KeyError.
Common mistakes
Four traps appear often.
Mixing up load and loads. Passing a string to json.load() fails because it expects a file object.
Treating a string as a dictionary. If you forget to parse, indexing the text with a key gives a TypeError.
Using yaml.load on untrusted input. Prefer yaml.safe_load, which builds only plain types.
Forgetting that XML values are text. The value 42 read from XML is the string "42". Convert it with int() before you do arithmetic.
Do not paste a live token or password into a script that you share. Read secrets from the environment instead.
Check yourself
Work through these three questions.
Which function parses a JSON string, and which parses an open file?
json.loads()parses a string andjson.load()parses an open file.What Python type does a JSON object become, and what does a JSON array become?
An object becomes a dict and an array becomes a list.
Why use
yaml.safe_loadinstead ofyaml.load?safe_loadbuilds only plain Python types, so it is safer for data you did not write yourself.
Topic 2 of 7 in Software Development and Design
Test yourself on Software Development and Design
The full Cisco CCNA 200-901 DEVASC question bank has 808 questions, with timed practice exams and an explanation for every answer.
This study guide is independent and is not affiliated with, endorsed by, or sponsored by Cisco. Vendor names, certification names and exam codes are trademarks of their respective owners and are used for identification only.