2011-08-25 2 views
6

Je souhaite avoir une fonction personnalisée qui sérialise des objets python arbitraires, comme la fonction json.dump avec un argument facultatif appelé 'default', qui devrait être une fonction que le dumper json appellera si l'objet n'est pas sérialisable json.Comment écrire un représentant pour PYYAML?

Je veux simplement faire l'équivalent de cela à partir du paquet json.

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

On dirait que je dois écrire yaml.add_representer, des docs PyYAML, mais il est vraiment pas clair comment faire cela.

Répondre

3

Voici un exemple pour add_representer. Je ne sais pas si c'est exactement ce que vous voulez. Néanmoins ...

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

Bien sûr, il y a une duplication de code et le code n'est pas optimisé. Vous pouvez intégrer ces deux fonctions dans votre classe et implémenter __repr__ pour obtenir une représentation imprimable que vous pouvez utiliser pour renseigner serializedData dans MyClass_representer

+0

comment puis-je 'désenregistrer' le représentant et le constructeur ajoutés? Je travaille dans un environnement où il y a d'autres outils qui reposent sur des comportements différents, j'ai trouvé que si j'ajoute un tel comportement, cela changera le comportement du module yaml, même si le code qui s'appelle yaml est dans un autre module. – Shuman

+0

Comment est-ce que je fais ce travail pour une hiérarchie de classes (disons A (roor), B (root), C (root))? –

Questions connexes