11

my question is very simple. I have a OrderredDict object with customized order, I want to convert it to yaml format. But it seems yaml.dump couldn't take Orderredict as an Input. Anyone know how to do it?

yabchexu
  • 543
  • 7
  • 21

3 Answers3

12

It looks like you want this solution, which adds a "representer" to YAML.

Assuming you have an object my_object that consists of nested lists, dicts, and/or OrderedDicts ... you can dump this to YAML if you add these lines:

yaml.add_representer(OrderedDict, lambda dumper, data: dumper.represent_mapping('tag:yaml.org,2002:map', data.items()))
output = yaml.dump(my_object)

I also find it necessary to convert my tuples to lists:

yaml.add_representer(tuple, lambda dumper, data: dumper.represent_sequence('tag:yaml.org,2002:seq', data))
Ethan T
  • 1,390
  • 12
  • 28
2

This works only for dictionary, not OrderedDict, but you may be able to convert it without losing the order.

If you are using PyYaml 5.1 or later, you can dump a dictionary in its current order by simply using

yaml.dump(data, default_flow_style=False, sort_keys=False)
Phil B
  • 5,589
  • 7
  • 42
  • 58
1

Maybe this is what you need?

import yaml 
from collections import OrderedDict

def dump_ordered_yaml(ordered_data, output_filename, Dumper=yaml.Dumper):
    class OrderedDumper(Dumper):
        pass

    class UnsortableList(list):
        def sort(self, *args, **kwargs):
            pass

    class UnsortableOrderedDict(OrderedDict):
        def items(self, *args, **kwargs):
            return UnsortableList(OrderedDict.items(self, *args, **kwargs))

    OrderedDumper.add_representer(UnsortableOrderedDict, yaml.representer.SafeRepresenter.represent_dict)
    with open(output_filename, "w") as f:
        yaml.dump(ordered_data, f, Dumper=OrderedDumper)

Usage:

a = OrderedDict([('x', 11), ('y', 22)])
dump_ordered_yaml(a, "/tmp/ordered.yaml")

Result from terminal:

cat /tmp/ordered.yaml
!!python/object/apply:collections.OrderedDict
- - [x, 11]
  - [y, 22]
Yonatan Simson
  • 2,395
  • 1
  • 24
  • 35