recorrer objeto dict diccionario convertir python json django

objeto - python json to dict



Cómo convertir datos JSON en un objeto Python (9)

Aquí hay una alternativa rápida y sucia de jason pickle

import json class User: def __init__(self, name, username): self.name = name self.username = username def to_json(self): return json.dumps(self.__dict__) @classmethod def from_json(cls, json_str): json_dict = json.loads(json_str) return cls(**json_dict) # example usage User("tbrown", "Tom Brown").to_json() User.from_json(User("tbrown", "Tom Brown").to_json()).to_json()

Quiero usar Python para convertir datos JSON en un objeto Python.

Recibo objetos de datos JSON de la API de Facebook, que quiero almacenar en mi base de datos.

Mi vista actual en Django (Python) ( request.POST contiene el JSON):

response = request.POST user = FbApiUser(user_id = response[''id'']) user.name = response[''name''] user.username = response[''username''] user.save()

  • Esto funciona bien, pero ¿cómo manejo los objetos de datos JSON complejos?

  • ¿No sería mucho mejor si pudiera convertir de alguna manera este objeto JSON en un objeto de Python para facilitar su uso?


Consulte la sección titulada "Especialización de decodificación de objetos JSON" en los documentos del módulo json ( http://docs.python.org/library/json.html para Python v2.7.3). Hay una sección sobre decodificación de objetos especializados. Puede usar eso para decodificar un objeto JSON en un tipo específico de Python.

Aquí hay un ejemplo:

class User(object): def __init__(self, name, username): self.name = name self.username = username import json def object_decoder(obj): if ''__type__'' in obj and obj[''__type__''] == ''User'': return User(obj[''name''], obj[''username'']) return obj json.loads(''{"__type__": "User", "name": "John Smith", "username": "jsmith"}'', object_hook=object_decoder) print type(User) >>>> <class ''__restricted__.User''>

Actualizar

Si desea acceder a los datos en un diccionario a través del módulo json, haga esto:

user = json.loads(''{"__type__": "User", "name": "John Smith", "username": "jsmith"}'') print user[''name''] print user[''username'']

Como un diccionario normal.


Esto no es código de golf, pero aquí está mi truco más corto, usando types.SimpleNamespace como contenedor para objetos JSON.

En comparación con la principal solución de namedtuple , es:

  • probablemente más rápido / más pequeño ya que no crea una clase para cada objeto
  • corta
  • no hay opción de rename , y probablemente la misma limitación en las claves que no son identificadores válidos (utiliza setattr debajo de las cubiertas)

Ejemplo:

from __future__ import print_function import json try: from types import SimpleNamespace as Namespace except ImportError: # Python 2.x fallback from argparse import Namespace data = ''{"name": "John Smith", "hometown": {"name": "New York", "id": 123}}'' x = json.loads(data, object_hook=lambda d: Namespace(**d)) print (x.name, x.hometown.name, x.hometown.id)


He escrito un pequeño marco de serialización (de) llamado any2any que ayuda a hacer transformaciones complejas entre dos tipos de Python.

En su caso, supongo que desea json.loads de un diccionario (obtenido con json.loads ) a un objeto complejo response.education ; response.name response.education ; response.name , con una estructura anidada response.education.id , etc ... Así que eso es exactamente para lo que está hecho este framework. La documentación aún no es excelente, pero al usar any2any.simple.MappingToObject , debería poder hacer eso muy fácilmente. Por favor pregunta si necesitas ayuda.


Modificando la respuesta @DS un poco, para cargar desde un archivo:

def _json_object_hook(d): return namedtuple(''X'', d.keys())(*d.values()) def load_data(file_name): with open(file_name, ''r'') as file_data: return file_data.read().replace(''/n'', '''') def json2obj(file_name): return json.loads(load_data(file_name), object_hook=_json_object_hook)

Una cosa: esto no puede cargar elementos con números por delante. Me gusta esto:

{ "1_first_item": { "A": "1", "B": "2" } }

Porque "1_first_item" no es un nombre de campo python válido.


Para objetos complejos, puede usar JSON Pickle

Biblioteca de Python para serializar cualquier gráfico de objetos arbitrarios en JSON. Puede tomar casi cualquier objeto de Python y convertir el objeto en JSON. Además, puede reconstituir el objeto nuevamente en Python.


Puedes hacerlo en una línea, usando namedtuple y object_hook :

import json from collections import namedtuple data = ''{"name": "John Smith", "hometown": {"name": "New York", "id": 123}}'' # Parse JSON into an object with attributes corresponding to dict keys. x = json.loads(data, object_hook=lambda d: namedtuple(''X'', d.keys())(*d.values())) print x.name, x.hometown.name, x.hometown.id

o, para reutilizar esto fácilmente:

def _json_object_hook(d): return namedtuple(''X'', d.keys())(*d.values()) def json2obj(data): return json.loads(data, object_hook=_json_object_hook) x = json2obj(data)

Si desea que maneje claves que no son buenos nombres de atributos, consulte el parámetro de rename namedtuple .


Puedes intentar esto:

class User(object): def __init__(self, name, username, *args, **kwargs): self.name = name self.username = username import json j = json.loads(your_json) u = User(**j)

Simplemente crea un nuevo objeto y pasa los parámetros como un mapa.