How to Convert YAML to List of Objects in Python
In this tutorial, you’ll learn how to convert YAML data into a list of Python objects using various methods.
We’ll cover simple conversions using dictionaries, using custom classes, handling nested structures, and dealing with cyclic references.
Custom Class for Object Creation
To convert YAML data into instances of a custom class, you can define a class and use a custom constructor with PyYAML.
import yaml
class Person:
def __init__(self, name, age, city):
self.name = name
self.age = age
self.city = city
def person_constructor(loader, node):
values = loader.construct_mapping(node)
return Person(**values)
class CustomLoader(yaml.SafeLoader):
pass
CustomLoader.add_constructor('!Person', person_constructor)
yaml_data = """
- !Person
name: Omar
age: 28
city: Giza
- !Person
name: Mona
age: 32
city: Luxor
"""
people = yaml.load(yaml_data, Loader=CustomLoader)
for person in people:
print(f"{person.name} is {person.age} years old and lives in {person.city}")
Output:
Omar is 28 years old and lives in Giza Mona is 32 years old and lives in Luxor
Each YAML item is loaded into a Person object, and you print out their details.
Custom Class for Nested Objects
For YAML data with nested structures, you can create nested classes and adjust the constructor to handle them.
import yaml
class Address:
def __init__(self, city, street):
self.city = city
self.street = street
class Person:
def __init__(self, name, age, address):
self.name = name
self.age = age
self.address = address
def address_constructor(loader, node):
values = loader.construct_mapping(node)
return Address(**values)
def person_constructor(loader, node):
values = loader.construct_mapping(node)
return Person(**values)
class CustomLoader(yaml.SafeLoader):
pass
CustomLoader.add_constructor('!Person', person_constructor)
CustomLoader.add_constructor('!Address', address_constructor)
yaml_data = """
- !Person
name: Salma
age: 27
address: !Address
city: Aswan
street: Nile Avenue
"""
people = yaml.load(yaml_data, Loader=CustomLoader)
person = people[0]
print(f"{person.name} is {person.age} years old and lives on {person.address.street}, {person.address.city}")
Output:
Salma is 27 years old and lives on Nile Avenue, Aswan
The nested Address object is properly constructed and associated with the Person object.
Using YAMLObject
You can use yaml.YAMLObject to map YAML entries to Python objects without custom constructors.
import yaml
yaml_data = """
!Person
name: Karim
age: 35
city: Hurghada
"""
class Person(yaml.YAMLObject):
yaml_tag = '!Person'
def __init__(self, name, age, city):
self.name = name
self.age = age
self.city = city
person = yaml.load(yaml_data, Loader=yaml.Loader)
print(f"{person.name} is {person.age} years old and lives in {person.city}")
Output:
Karim is 35 years old and lives in Hurghada
Handle Cyclic References
When dealing with YAML data that has cyclic references, you can enable the resolver in PyYAML to handle them.
import yaml yaml_data = """ a: &id001 name: Ali friend: *id001 """ data = yaml.safe_load(yaml_data) print(data['a']['friend']['name'])
Output:
Ali
The cyclic reference is resolved, and you can access the nested data without causing infinite recursion.
Mokhtar is the founder of LikeGeeks.com. He is a seasoned technologist and accomplished author, with expertise in Linux system administration and Python development. Since 2010, Mokhtar has built an impressive career, transitioning from system administration to Python development in 2015. His work spans large corporations to freelance clients around the globe. Alongside his technical work, Mokhtar has authored some insightful books in his field. Known for his innovative solutions, meticulous attention to detail, and high-quality work, Mokhtar continually seeks new challenges within the dynamic field of technology.