231 votos

Python: Cómo hacer una clase JSON serializable

Entonces, esa es la pregunta:
¿Cómo hacer una clase serializable?

una clase simple:

class FileItem:
    def __init__(self, fname):
        self.fname = fname

¿Qué debo hacer para poder conseguir la salida de:

json.dumps()

sin un error ( FileItem instance at ... is not JSON serializable )

187voto

Manoj Govindan Puntos 24030

¿Tienes una idea sobre el resultado esperado? Por ejemplo. hará esto?

>>> f  = FileItem("/foo/bar")
>>> magic(f)
'{"fname": "/foo/bar"}'

En ese caso, usted puede simplemente llame json.dumps(f.__dict__).

Si quieres personalizar más la salida, entonces usted tendrá que subclase JSONEncoder la implementación de la serialización personalizada.

Para un ejemplo, vea a continuación.

>>> from json import JSONEncoder
>>> class MyEncoder(JSONEncoder):
    def default(self, o):
        return o.__dict__    

>>> MyEncoder().encode(f)
'{"fname": "/foo/bar"}'

Luego de pasar de esta clase en la json.dumps() método como cls kwarg:

json.dumps(cls=MyEncoder)

Si usted también desea decodificar, a continuación, usted tendrá que suministrar una costumbre object_hook a JSONDecoder de la clase. Por ejemplo.

>>> def from_json(json_object):
        if 'fname' in json_object:
            return FileItem(json_object['fname'])
>>> f = JSONDecoder(object_hook = from_json).decode('{"fname": "/foo/bar"}')
>>> f
<__main__.FileItem object at 0x9337fac>
>>> 

179voto

Onur Yıldırım Puntos 5566

Aquí es una solución simple para una simple característica:

.to_JSON()Método

En lugar de una clase serializable JSON, implementar un método de serializador:

import json

class Object:
    def to_JSON(self):
        return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4)

Así llamarlo para serializar:

me = Object()
me.name = "Onur"
me.age = 35
me.dog = Object()
me.dog.name = "Apollo"

print(me.to_JSON())

salida:

{
    "age": 35,
    "dog": {
        "name": "Apollo"
    },
    "name": "Onur"
}

35voto

gecco Puntos 4063

Para obtener más complejo clases que usted podría considerar la posibilidad de la herramienta jsonpickle:

jsonpickle es una biblioteca de Python para la serialización y deserialización de complejo de objetos de Python y de JSON.

El estándar de librerías de Python para la codificación de Python en JSON, tales como la stdlib del json, simplejson, y demjson, sólo puede manejar Python primitivas que tienen un directo JSON equivalente (por ej. dicts, listas, cadenas de caracteres, enteros, etc.). jsonpickle construye en la parte superior de estas bibliotecas y permite estructuras de datos más complejas a ser serializado en JSON. jsonpickle es altamente configurable y extensible, permitiendo al usuario elegir el JSON de backend y agregar otros backends.

(jsonpickle en PyPi)

9voto

Paulo Freitas Puntos 3039

Otro caso es envolver JSON dumping en la propia clase:

import json

class FileItem:
    def __init__(self, fname):
        self.fname = fname

    def __repr__(self):
        return json.dumps(self.__dict__)

O incluso crear subclases de FileItem clase de una clase de JSONSeriazable:

import json

class JSONSeriazable(object):
    def __repr__(self):
        return json.dumps(self.__dict__)

class FileItem(JSONSeriazable):
    def __init__(self, fname):
        self.fname = fname

Prueba:

>>> f = FileItem('/foo/bar')
>>> f
'{"fname": "/foo/bar"}'
>>> str(f) # string coercion
'{"fname": "/foo/bar"}'

1voto

danbrough Puntos 866

Aquí está mis 3 centavos...
Esto demuestra la serialización json explícito para un objeto de tipo árbol de python.
Nota: Si usted en realidad quería algo de código así te vendría la clase torcido FilePath .

import json, sys, os

class File:
    def __init__(self, path):
        self.path = path

    def isdir(self):
        return os.path.isdir(self.path)

    def isfile(self):
        return os.path.isfile(self.path)

    def children(self):        
        return [File(os.path.join(self.path, f)) 
                for f in os.listdir(self.path)]

    def getsize(self):        
        return os.path.getsize(self.path)

    def getModificationTime(self):
        return os.path.getmtime(self.path)

def _default(o):
    d = {}
    d['path'] = o.path
    d['isFile'] = o.isfile()
    d['isDir'] = o.isdir()
    d['mtime'] = int(o.getModificationTime())
    d['size'] = o.getsize() if o.isfile() else 0
    if o.isdir(): d['children'] = o.children()
    return d

folder = os.path.abspath('.')
json.dump(File(folder), sys.stdout, default=_default)

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: