Search code examples
pythonyamlpython-dataclassespyyaml

How can I dump a Python dataclass to YAML without tags?


I have a nested dataclasses that I would like to convert and save to the yaml format using the PyYaml library. The resultant YAML output contains YAML tags which I would like to remove.

I have the following Python code:

from dataclasses import dataclass
import yaml


@dataclass
class Database:
    host: str
    username: str
    password: str


@dataclass
class Environment:
    name: str
    database: Database


@dataclass
class Config:
    environment: Environment


database = Database(host="localhost", username="admin", password="secret")
environment = Environment(name="local", database=database)
config = Config(environment=environment)
print(yaml.dump(config))

which produces the YAML output:

!!python/object:__main__.Config
environment: !!python/object:__main__.Environment
  database: !!python/object:__main__.Database
    host: localhost
    password: secret
    username: admin
  name: local

How can I produce a YAML output of nested dataclasses without the YAML tags included? The desired outcome should look something like:

environment:
  database:
    host: localhost
    password: secret
    username: admin
  name: local

Solution

  • When dumping instances of Python classes, PyYaml will serialize the contents and add a tag indicating the class in order to allow reading the yaml output back to the designated class. PyYaml does not tag native Python objects like lists and dicts, so by converting the dataclass instances to dictionaries with the asdict method the YAML dump will contain no tags:

    from dataclasses import dataclass, asdict
    import yaml
    
    
    @dataclass
    class Database:
        host: str
        username: str
        password: str
    
    
    @dataclass
    class Environment:
        name: str
        database: Database
    
    
    @dataclass
    class Config:
        environment: Environment
    
    
    database = Database(host="localhost", username="admin", password="secret")
    environment = Environment(name="local", database=database)
    config = Config(environment=environment)
    print(yaml.dump(asdict(config)))
    

    The updated code above produces the following output:

    environment:
      database:
        host: localhost
        password: secret
        username: admin
      name: local