phonenumber - python serialize class to json
Cómo hacer una clase serializable simplejson (2)
Tengo una clase definida así
class A:
def __init__(self):
self.item1 = None
def __repr__(self):
return str(self.__dict__)
Cuando lo hago:
>>> 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?
De acuerdo con los documentos del módulo json (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.
No puede serializar objetos arbitrarios con simplejson
. object_hook
pasar un default
y object_hook
para dump
y load
. Aquí hay 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 resulta en esto:
>>> s
''{"item1": 1, "__type__": ["__main__", "A"]}''
>>> a
{''item1'': 1}
Pero lo que realmente necesita es una función default
que crea el diccionario a partir de los objetos que desea serializar, y una función object_hook
que devuelve un objeto (del tipo correcto) cuando se le asigna un diccionario si el 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 para usar como índice para _classes
. De esta forma no tendrías problemas si tienes que mover una clase.