2010-09-09 18 views
5

Soy bastante nuevo en python (uso python 3), y estoy tratando de serializar una clase con una cadena y dos listas como miembros en JSon. Descubrí que hay una json lib en el estándar de python, pero parece que necesito implementar manualmente un método de serialización. ¿Hay un codificador JSon donde simplemente pueda pasar un objeto y recibir el objeto serializado como una cadena sin tener que implementar un método de serialización? Ejemplo:Codificación JSON fácil con Python

class MyClass: 
    pass 

if __name__ == '__main__': 
    my_name = "me" 
    my_list = {"one","two"} 
    my_obj = MyClass() 
    my_obj.name = my_name; 
    my_obj.my_list = my_list 


    serialized_object = JSONserializer.serialize(my_obj). 

Gracias.

+0

¿La versión de Python es importante? Quiero decir, ¿puedes hacerlo en 2.x, pero no puedes hacerlo en 3.0? – esylvestre

+0

Sí, sí, la mayoría de las bibliotecas parece haber cambiado de 2.x a 3. –

Respuesta

3

No sabe nada de pre-construido, pero se puede escribir uno si los objetos son bastante simples. Anule el método predeterminado en JSONEncoder para ver inspeccionar.obtener miembros (obj) (inspeccionar es una forma más legible de obtener conjuntos de atributos en __dict__).

#!/usr/bin/env python3 

import inspect 
from json import JSONEncoder 


class TreeNode: 

    def __init__(self, value, left=None, right=None): 
     self.value = value 
     self.left = left 
     self.right = right 


class ObjectJSONEncoder(JSONEncoder): 

    def default(self, reject): 
     is_not_method = lambda o: not inspect.isroutine(o) 
     non_methods = inspect.getmembers(reject, is_not_method) 
     return {attr: value for attr, value in non_methods 
       if not attr.startswith('__')} 


if __name__ == '__main__': 
    tree = TreeNode(42, 
     TreeNode(24), 
     TreeNode(242), 
    ) 
    print(ObjectJSONEncoder().encode(tree)) 

Actualización: @Alexandre Deschamps dice isroutine funciona mejor que es el método por alguna entrada.

+0

Gracias por el awser, casi funciona, excepto por dos cosas. The is_not_method = lambda o: not inspect.ismethod (o) parece necesitar también la instrucción non inspect.isroutine (o). Parece que en python un método incorporado es un caso límite. Además, mi clase necesita una lista para ser serializada. parece que los elementos de la lista no se serializan con él. –

+0

@Alexandre Deschamps: No entiendo lo que quieres decir ... si cambias esos números en '__main__' a listas de números, se serializa muy bien. – cdleary

+0

Ok, descubrí que era el problema. Estaba usando {} en lugar de [] para hacer una lista. Como dije, soy nuevo en el lenguaje. Funciona bien. Simplemente agregue el "no inspeccionar. Riego" a su ejemplo en caso de que otras personas lo necesiten. Muchas gracias por su tiempo. –

0

¿Qué tal la clase JSONEncoder?

actualización

Debo haber saltado la parte de los datos que se están contenidas en una clase. Si desea una serialización correcta de los objetos arbitrarios de Python sin la necesidad de extender el codificador, entonces tal vez pueda usar una combinación de pickle y json. Cuando se decapa, use protocol = 0 para serializar los datos como ASCII legible para humanos.

+0

Aún así, necesito codificar una clase, y no solo un tipo simple o una matriz. Esta clase parece requerir un método de serialización definido manualmente para serializar una clase. Tal vez estoy equivocado ya que soy nuevo con el idioma, pero cuando probé eso es lo que obtuve. –

+0

@Alexandre - actualizado mi respuesta –

+0

'La idea de pickle' del legible es:' (i__main__ Mapa p0 (DP1 S'towers' p2 (lp3 (i__main__ Torre p4 (DP5 S'attack ' P6 I10 sbasS'creeps' p7 (LP8 S'one fluencia cadena en una lista' P9 asb.' en comparación con JSON, que es difícilmente legible. – Pat

4

¿Cómo espera que la biblioteca json sepa cómo serializar las clases arbitrarias?

En su caso, si la clase es bastante simple, es posible que pueda escapar algo así como

foo = FooObject() # or whatever 
json_string = json.dumps(foo.__dict__) 

sólo serializar los miembros del objeto.

Deserialización continuación, tendría que ser algo como

foo_data = json.loads(json_string) 
foo = FooObject(**foo_data) 
+0

Nah, parece que no funciona porque mi clase tiene dos miembros, que es una cadena y una lista de cadenas –

+0

Funciona para mí: http://gist.github.com/574291. Si su objeto realmente solo tiene dos miembros, una cadena y una lista de cadenas, entonces la serialización funcionará. La técnica de deserialización que estoy utilizando se basa en la función '__init__' de su objeto para tomar argumentos con los mismos nombres que los miembros. Ver la esencia de arriba para un ejemplo de trabajo. –

+0

@WillMcCutchen Gracias por la inspiración de usar 'dict'. Quería hacer algo similar, y aunque mi objeto (de una solicitud SOAP) no tenía un método '__dict__', al llamar' dict (soapObj) 'me dio una cadena JSON impresa muy bien. También soy nuevo en Python, y esta no es una técnica obvia, ¡así que me alegra que lo hayas mencionado! – Pat

Cuestiones relacionadas