2010-03-07 16 views
11

ho i seguenti metodi semplici per la scrittura di un oggetto Python in un file utilizzando jsonpickle:salvare e caricare gli oggetti da file utilizzando jsonpickle

def json_serialize(obj, filename, use_jsonpickle=True): 
    f = open(filename, 'w') 
    if use_jsonpickle: 
     import jsonpickle 
     json_obj = jsonpickle.encode(obj) 
     f.write(json_obj) 
    else: 
     simplejson.dump(obj, f) 
    f.close() 

def json_load_file(filename, use_jsonpickle=True): 
    f = open(filename) 
    if use_jsonpickle: 
     import jsonpickle 
     json_str = f.read() 
     obj = jsonpickle.decode(json_str) 
    else: 
     obj = simplejson.load(f) 
    return obj 

il problema è che ogni volta che uso questi, carica miei oggetti indietro come dizionari (che hanno campi come: "py/object": "my_module.MyClassName") ma non come un vero oggetto Python del tipo che è stato usato per generare la stringa json. Come posso fare in modo che jsonpickle converta effettivamente la stringa caricata sull'oggetto?

illustrare con un esempio, considerare quanto segue:

class Foo: 
    def __init__(self, hello): 
    self.hello = hello 

# make a Foo obj 
obj = Foo("hello world") 
obj_str = jsonpickle.encode(obj) 
restored_obj = jsonpickle.decode(obj_str) 
list_objects = [restored_obj] 
# We now get a list with a dictionary, rather than 
# a list containing a Foo object 
print "list_objects: ", list_objects 

Questo produce:

list_objects: [{'py/object': 'as_events.Foo', 'hello': 'hello world'}] 

Piuttosto che qualcosa di simile a: [Foo()]. Come posso risolvere questo?

grazie.

+0

Puoi importare as_events' prima della riga 'jsonpickle.decode()'? – jfs

+0

FWIW questo è un ottimo esempio di quando si dovrebbe usare il 'con open()' gestore di contesto per la scrittura di file. Quando ti imbatti in errori di serializzazione qui lascerai i tuoi file aperti - questo è male. – BoltzmannBrain

risposta

17

La risposta corretta era che non ero che eredita da object. Senza ereditare da object, jsonpickle non può decodificare correttamente le classi che accettano uno o più argomenti nel costruttore, a quanto pare. Non sono affatto un esperto ma lo ho reso Foo(object): anziché Foo: nella dichiarazione della classe risolto.

2

Verificare che use_jsonpickle == True in json_load_file(). Sembra che si serializzi usando jsonpickle e si carichi usando json.

>>> import jsonpickle 
>>> class A(object): 
... def __init__(self, name): 
...  self.name = name 
... 
>>> js = jsonpickle.encode(A('abc')) 
>>> js 
'{"py/object": "__main__.A", "name": "abc"}'  # <-- json string 
>>> a = jsonpickle.decode(js) 
>>> a 
<__main__.A object at 0x7f826a87bd90>   # <-- python object 
>>> a.name 
u'abc' 
>>> import json 
>>> b = json.loads(js) 
>>> b 
{u'py/object': u'__main__.A', u'name': u'abc'} # <-- dictionary 

Assicurarsi che tipo di oggetto è disponibile

>>> del A 
>>> c = jsonpickle.decode(js)     # no type available 
>>> c 
{u'py/object': u'__main__.A', u'name': u'abc'} 
>>> type(c) 
<type 'dict'> 
>>> class A(object): 
... def __init__(self, name): 
...  self.name = name 
... 
>>> d = jsonpickle.decode(js)     # type is available 
>>> d 
<__main__.A object at 0x7f826a87bdd0> 
>>> type(d) 
<class '__main__.A'> 
+0

Qualcuno può dirmi cosa è questa cosa "u" in {u'py/object ': u' __ main __. A ', u'name': u'abc '}? – ed22

+0

@ ed22 è [come i letterali stringa unicode sono scritti in Python 2] (https://docs.python.org/2/howto/unicode.html#unicode-literals-in-python-source-code). 'repr (unicode_string)' usa la stessa rappresentazione di testo. – jfs

+0

Grazie mille! – ed22

Problemi correlati