2010-03-07 14 views
11

tengo los siguientes métodos simples para escribir un objeto de Python en un archivo utilizando jsonpickle:guardar y cargar objetos de archivo utilizando 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 

el problema es que cada vez que use estos, se carga los objetos de mi espalda mientras diccionarios (que tienen campos como: "py/object": "my_module.MyClassName") pero no como un objeto de Python real del tipo que se utilizó para generar la cadena json. ¿Cómo puedo hacer que jsonpickle realmente convierta la cadena cargada al objeto?

Para ilustrar esto con un ejemplo, considere la siguiente:

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 

Este rendimientos:

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

En lugar de algo como: [Foo()]. ¿Cómo puedo arreglar esto?

gracias.

+0

¿Se puede 'importar como_eventos' antes de' jsonpickle.decode() 'línea? – jfs

+0

FWIW Este es un gran ejemplo de cuándo debe usar el administrador de contexto 'with open()' para la escritura de archivos. Cuando encuentre serialización de errores aquí, dejará sus archivos abiertos, eso es malo. – BoltzmannBrain

Respuesta

17

La respuesta correcta era que no estaba heredando de object. Sin heredar de object, jsonpickle no puede decodificar correctamente las clases que toman uno o más argumentos en el constructor, parece. De ninguna manera soy un experto, pero al hacerlo Foo(object): en lugar de Foo: en la declaración de clase lo arreglé.

2

Asegúrese de que use_jsonpickle == True en json_load_file(). Parece que serializas usando jsonpickle y cargas 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 

Asegúrese de que el tipo de objeto está disponible

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

¿Alguien puede decirme qué es esta cosa "u" en {u'py/object ': u' __ principal __. A ', u'name': u'abc '}? – ed22

+0

@ ed22 es [cómo los literales de cadenas unicode se escriben en Python 2] (https://docs.python.org/2/howto/unicode.html#unicode-literals-in-python-source-code). 'repr (unicode_string)' usa la misma representación de texto. – jfs

+0

¡Muchas gracias! – ed22

Cuestiones relacionadas