2011-08-25 12 views
6

Desidero avere una funzione personalizzata che serializzi oggetti Python arbitrari, come il modo in cui la funzione json.dump ha un argomento facoltativo chiamato 'default', che dovrebbe essere una funzione che il jumper dumper chiamerà se l'oggetto non è serializzabile json.Come si scrive un rappresentatore per PyYAML?

Voglio semplicemente fare l'equivalente di questo dal pacchetto json.

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

sembra che ho bisogno di scrivere yaml.add_representer, dalla documentazione PyYAML, ma in realtà non è chiaro come fare questo.

risposta

3

Ecco un esempio per add_representer. Non sono sicuro se questo è esattamente quello che vuoi. Tuttavia ...

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

Naturalmente c'è la duplicazione del codice e il codice non è ottimizzato. È possibile effettuare queste due funzioni parte della vostra classe, e anche implementare __repr__ per ottenere una rappresentazione stampabile che è possibile utilizzare per popolare serializedData in MyClass_representer

+0

come faccio 'annullare la registrazione' il representer aggiunto e costruttore di allora? Lavoro in un ambiente che ci sono altri strumenti che si basano su un comportamento diverso, ho scoperto che se aggiungo rappresentatore e costruttore come questo, cambierà il comportamento del modulo yaml, anche se il codice che ha chiamato yaml si trova in un altro file in un altro modulo. – Shuman

+0

Come faccio a fare in modo che funzioni per una gerarchia di classi (ad esempio A (roor), B (root), C (root))? –

Problemi correlati