Chameleon
Chameleon

Reputation: 10138

How to do yaml.safe_dump() and .safe_load() of Python object without yaml.YAMLObject?

I want to serialize some object with yaml.safe_dump(). How can I serialize Python objects with add_representer() and add_constructor() ...

I can not add yaml.YAMLObject to Thing (third party module) and not want use.

I do such dump:

import yaml

class Thing(object):
  def __init__(self, name):
    self.name = name

def Thing_representer(dumper, data):
  return dumper.represent_mapping('!Thing', data.__dict__)

yaml.SafeDumper.add_representer(Thing, Thing_representer)
safe_dump = yaml.safe_dump(t)
print safe_dump

It works fine but I have no idea how to do constructor?

def Thing_constructor(loader, data):
  thing = Thing()
  return thing.__dict__.update(loader.construct_mapping(data))

yaml.SafeLoader.add_constructor('!Thing', Thing_constructor)
yaml.safe_load(safe_dump)

It throws exception TypeError: __init__() takes exactly 2 arguments (1 given) and should throw since constructor requires parameters. Maybe there is another option to construct object skipping constructor?

Upvotes: 4

Views: 6176

Answers (1)

Anthon
Anthon

Reputation: 76812

You cannot construct Thing() without handing in the name. You can solve that in various ways, but the following should work.

def thing_constructor(self, node):
    name = None
    for x in node.value:
        if x[0].value == 'name':
            name = x[1].value
    return Thing(name)


yaml.SafeLoader.add_constructor('!Thing', thing_constructor)

res = yaml.safe_load(safe_dump)
print res.name

You can simplify the setting of the name parameter, but this way it is more extensible if Thing would have taken more parameters.

Upvotes: 3

Related Questions