如何为PyYAML编写表示器?

10 投票
1 回答
10500 浏览
提问于 2025-04-17 00:18

我想要一个自定义的函数,可以把任意的Python对象转换成可以存储的格式,就像json.dump函数有一个可选的参数叫'default',这个参数是一个函数,当对象无法被转换成json格式时,json的处理程序会调用这个函数。

我只是想做一些和json包里类似的事情。

json.dump(tests_dump, file('somefile', 'w+'), default = lambda x: x.__dict__)

看起来我需要使用yaml.add_representer,来自PyYAML的文档,但具体该怎么做并不太清楚。

1 个回答

8

这里有一个关于add_representer的示例。不确定这是否正是你想要的。不过……

import yaml

#Arbitrary Class
class MyClass:
  def __init__(self, someNumber, someString):
    self.var1 = someNumber
    self.var2 = someString

#define the representer, responsible for serialization
def MyClass_representer(dumper, data):
    serializedData = str(data.var1) + "|" + data.var2
    return dumper.represent_scalar('!MyClass', serializedData )

#'register' it     
yaml.add_representer(MyClass, MyClass_representer)

obj = MyClass(100,'test')

print ( 'original Object\nvar1:{0}, var2:{1}\n'.format(obj.var1, obj.var2) )

#serialize
yamlData = yaml.dump(obj)

print('serialized as:\n{0}'.format(yamlData) )

#Now to deserialize you need a constructor
def MyClass_constructor(loader,node):
    value = loader.construct_scalar(node)
    someNumber,sep,someString = value.partition("|")
    return MyClass(someNumber,someString)

#'register' it    
yaml.add_constructor('!MyClass', MyClass_constructor)

#deserialize
obj2 = yaml.load(yamlData)

print ( 'after deserialization\nvar1:{0}, var2:{1}\n'.format(obj2.var1, obj2.var2) )

当然,这里有代码重复,而且代码也没有经过优化。你可以把这两个函数放到你的类里面,并且实现一下__repr__方法,这样就能得到一个可以打印的表示,方便你在MyClass_representer中填充serializedData

撰写回答