2011-01-27 11 views
7

tengo una clase definida como estoCómo hacer simplejson clase serializable

class A: 
    def __init__(self): 
     self.item1 = None 
    def __repr__(self): 
     return str(self.__dict__) 

cuando lo haga:

>>> import simplejson 
>>> myA = A() 
>>> simplejson.dumps(myA) 
TypeError: {'item1': None} is not JSON serializable 

No puedo encontrar la razón por qué.

¿Debo agregar algún método en particular a A para que simplejson serialice mi objeto de clase?

Respuesta

10

No puede serializar objetos arbitrarios con simplejson. Debe pasar un default y object_hook a dump y load. He aquí un ejemplo:

class SerializerRegistry(object): 
    def __init__(self): 
     self._classes = {} 
    def add(self, cls): 
     self._classes[cls.__module__, cls.__name__] = cls 
     return cls 
    def object_hook(self, dct): 
     module, cls_name = dct.pop('__type__', (None, None)) 
     if cls_name is not None: 
      return self._classes[module, cls_name].from_dict(dct) 
     else: 
      return dct 
    def default(self, obj): 
     dct = obj.to_dict() 
     dct['__type__'] = [type(obj).__module__, 
          type(obj).__name__] 
     return dct 

registry = SerializerRegistry() 

@registry.add 
class A(object): 
    def __init__(self, item1): 
     self.item1 = item1 
    def __repr__(self): 
     return str(self.__dict__) 
    def to_dict(self): 
     return dict(item1=self.item1) 
    @classmethod 
    def from_dict(cls, dct): 
     return cls(**dct) 

s = json.dumps(A(1), default=registry.default) 
a = json.loads(s, object_hook=registry.object_hook) 

Esto se traduce en lo siguiente:

>>> s 
'{"item1": 1, "__type__": ["__main__", "A"]}' 
>>> a 
{'item1': 1} 

Pero lo que realmente necesita es una función default que crea el diccionario de los objetos que desea serializar, y una función object_hook que devuelve un objeto (del tipo correcto) cuando se le da un diccionario si un diccionario no es suficiente. El mejor enfoque es tener métodos en las clases serializables que crean un dict del objeto y que lo reconstruyen, y también para tener un mapeo que reconoce a qué clase pertenecen los diccionarios.

También puede agregar un identificador a las clases que se utilizarán como índice para _classes. De esta forma no tendrías problemas si tienes que mover una clase.

+0

esta respuesta es correcta, pero no la compruebo porque el ejemplo no es muy simple. ¡Gracias! – dnuske

3

De acuerdo con json module docs (simplejson se adoptó como json en Python 2.6), necesita extender la clase json.JSONEncoder, anulando su método predeterminado para traducir su objeto a un tipo que se puede serializar. No parece haber un método que busque en su objeto.

Cuestiones relacionadas