Every network automation interface speaks in one of three data formats. RESTCONF uses JSON. NETCONF uses XML. Ansible and most human-authored config data use YAML. They all express the same thing - structured data - and once you see that they are three encodings of the same underlying model, the automation stack stops looking like a pile of unrelated tools and starts looking coherent.
This article takes one interface configuration and renders it as JSON, XML, and YAML side by side - all generated for real from one Python dictionary in the lab - and explains when each is used. It extends the network automation guide.
The key insight: same data, three encodings
A network device's configuration is structured data: an interface has a name, a description, an IP address (which itself has an address and a mask), an enabled flag. That structure - nested key-value pairs and lists - is the same regardless of how you write it down. JSON, XML, and YAML are three ways to write down the same structure.
In the lab, we started with one Python dictionary and rendered it three ways. Here is the dictionary as each format.
YAML - the human-authored source
interface:
name: Loopback200
description: DATA-FORMAT-DEMO
ipv4:
address: 172.30.1.1
netmask: 255.255.255.0
enabled: trueJSON - the RESTCONF payload
{
"interface": {
"name": "Loopback200",
"description": "DATA-FORMAT-DEMO",
"ipv4": {
"address": "172.30.1.1",
"netmask": "255.255.255.0"
},
"enabled": true
}
}XML - the NETCONF payload
<config>
<interface>
<name>Loopback200</name>
<description>DATA-FORMAT-DEMO</description>
<ipv4>
<address>172.30.1.1</address>
<netmask>255.255.255.0</netmask>
</ipv4>
<enabled>true</enabled>
</interface>
</config>Read all three and you see the same tree: an interface with a name, description, a nested ipv4 object, and an enabled flag. Only the syntax differs. A parser reads any of them into the same in-memory structure, which is exactly why you can convert freely between them - as we did, generating all three from one dict.
Where each is used, and why
Strength: the most human-readable - minimal punctuation, indentation-based. You write and review it by hand.
Weakness: whitespace-sensitive; a stray indent is an error.
Strength: universally supported, compact, native to JavaScript and easy in every language.
Weakness: no comments, more punctuation than YAML, no schema by itself.
Strength: namespaces, attributes, mature schema/validation (XSD), the format NETCONF was built on.
Weakness: verbose - the closing tags double the volume - and heavier to author by hand.
The mapping to network interfaces
The reason this matters is that the format follows the transport:
- Automate a device with NETCONF? You are sending and receiving XML. The
ncclientPython library builds and parses it. - Automate with RESTCONF? You are sending and receiving JSON (or XML - RESTCONF supports both, but JSON is the common choice). The
requestslibrary does the HTTP. - Author your config data for Ansible or a Jinja pipeline? You write YAML, and the tooling converts it to whatever the transport needs.
All three formats describe data structured according to a YANG model - the schema that defines what a valid interface configuration looks like. YANG is format-agnostic: the same YANG model can be encoded as XML (for NETCONF) or JSON (for RESTCONF). So the real picture is: YANG defines the structure; JSON and XML are how that structure travels; YAML is how you author it.
Converting between them in Python
Because they are the same data, conversion is trivial - load one format into a Python object, dump it as another:
import json, yaml
# YAML in
data = yaml.safe_load(open('interface.yml'))
# JSON out (for a RESTCONF PUT)
json_payload = json.dumps(data, indent=2)
# YAML back out
yaml_again = yaml.safe_dump(data)XML is slightly more involved (libraries like xmltodict or lxml handle it), but the principle is identical: parse to a common structure, serialise to the target format. This is exactly what we did in the lab to produce all three from one dictionary. The format is a serialisation detail; the data is what matters.
The practical workflow
- Author in YAML. It is the most readable, and it is what you review in a pull request.
- Convert to the transport's format - JSON for RESTCONF, XML for NETCONF - programmatically, at push time.
- Parse the device's response (JSON or XML) back into a Python structure to verify or extract data.
- Never hand-author XML for NETCONF if you can avoid it. Build it from a structure; the verbosity makes hand-editing error-prone.
This workflow means you think in data, not in formats. You describe the interface once, and the tooling handles the encoding for whichever interface you happen to be using.
Key takeaways
- JSON, XML, and YAML are three encodings of the same structured data. We proved it by rendering one Python dictionary as all three, identical in structure.
- YAML for humans (Ansible, config-as-data, Jinja pipelines), JSON for APIs (RESTCONF, REST), XML for NETCONF (and legacy enterprise systems).
- The format follows the transport: NETCONF = XML, RESTCONF = JSON, Ansible authoring = YAML.
- All three describe data structured by a YANG model - YANG defines the structure, JSON/XML carry it, YAML authors it.
- Conversion is trivial in Python because they are the same data - parse to a structure, serialise to the target format.
- Think in data, not formats. Author in YAML, convert programmatically, never hand-author XML.
Next: Advanced EEM - Tcl, multi-event correlation, and EEM + Python. The full cluster index lives on the network automation pillar.