如何将JSON数据转换为Python对象
我想使用Python将JSON数据转换为Python对象。
我从Facebook API接收JSON数据对象,我想将其存储在我的数据库中。
我目前在Django的视图(Python)( request.POST
包含JSON):
response = request.POST user = FbApiUser(user_id = response['id']) user.name = response['name'] user.username = response['username'] user.save()
-
这工作正常,但我如何处理复杂的JSON数据对象?
-
如果我能以某种方式将这个JSON对象转换成Python对象以方便使用,会不会更好?
你可以在一行中使用object_hook
和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
或者,轻松重复使用:
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)
如果你想要处理不好的属性名称的键,请检查namedtuple
的rename
参数 。
查看json模块文档( http://docs.python.org/library/json.html for Python v2.7.3)中标记为“专业化JSON对象解码”的部分 – 有专门的对象解码部分。 您可以使用它来将JSON对象解码为特定的Pythontypes。
这是一个例子:
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'>
更新
如果您想通过json模块访问字典中的数据,请执行以下操作:
user = json.loads('{"__type__": "User", "name": "John Smith", "username": "jsmith"}') print user['name'] print user['username']
就像一个普通的字典。
这不是代码高尔夫,但这里是我最短的把戏,使用types.SimpleNamespace
作为JSON对象的容器。
与领先的namedtuple
解决scheme相比,它是:
- 可能更快/更小,因为它不会为每个对象创build一个类
- 短
- 没有
rename
选项,并且可能是对不是有效标识符的密钥的相同限制(使用下面的setattr
)
例:
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)
你可以试试这个:
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)
只需创build一个新的对象,并将参数作为地图传递。
这是一个快速和肮脏的JSON泡菜替代品
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()
对于复杂的对象,可以使用JSON Pickle
用于将任意任意对象图序列化为JSON的Python库。 它几乎可以带任何Python对象,并把对象转换成JSON。 另外,它可以将对象重新组装成Python。
我写了一个名为any2any的小型(de)序列化框架,可以帮助在两种Pythontypes之间进行复杂的转换。
在你的情况下,我想你想从一个字典(用json.loads
获得)转换为一个复杂的对象response.education ; response.name
response.education ; response.name
,嵌套的结构response.education.id
等等…所以这正是这个框架的。 该文档还不是很好,但通过使用any2any.simple.MappingToObject
,你应该能够很容易地做到这一点。 请问你是否需要帮助。
稍微修改@DS响应,从文件加载:
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)
有一件事:这不能加载数字前面的项目。 喜欢这个:
{ "1_first_item": { "A": "1", "B": "2" } }
因为“1_first_item”不是有效的python字段名称。
使用json
模块 ( Python 2.6中的新增function )或几乎总是安装的simplejson
模块。