2011-08-25 15 views
6

Quiero tener una función personalizada que serialice objetos arbitrarios de python, como que la función json.dump tiene una arg opcional llamada 'predeterminada', que debería ser una función que el dumper json llamará si el objeto no es serializable json.¿Cómo escribo un representante para PyYAML?

Simplemente quiero hacer el equivalente a esto del paquete json.

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

Parece que tengo que escribir yaml.add_representer, a partir de los documentos PyYAML, pero realmente no está claro cómo hacer esto.

Respuesta

3

Aquí hay una muestra para add_representer. No estoy seguro si esto es exactamente lo que quieres. Sin embargo ...

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)) 

Por supuesto, hay una duplicación de código y el código no está optimizado. Puede hacer que estas dos funciones sean parte de su Clase, y también implementar __repr__ para obtener una representación imprimible que puede usar para completar serializedData en MyClass_representer

+0

¿cómo 'cancelaré' el representante y el constructor agregados? Trabajo en un entorno en el que hay otras herramientas que dependen de un comportamiento diferente, encontré que si agrego el representante y el constructor de esta manera, cambiará el comportamiento del módulo yaml, incluso si el código que llamó a yaml está en otro archivo en otro módulo. – Shuman

+0

¿Cómo hago esto para una jerarquía de clases (por ejemplo A (roor), B (raíz), C (raíz))? –

Cuestiones relacionadas