我想将JSON数据转换为Python对象。
我从Facebook API收到JSON数据对象,我想将其存储在数据库中。
我的当前视图在Django (Python)(请求。POST包含JSON):
response = request.POST
user = FbApiUser(user_id = response['id'])
user.name = response['name']
user.username = response['username']
user.save()
这很好,但是如何处理复杂的JSON数据对象呢?
如果我能以某种方式将这个JSON对象转换为易于使用的Python对象,是不是会更好?
数据类向导是一种现代的选项,可以类似地为您工作。它支持自动键大小写转换,如camelCase或TitleCase,这两者在API响应中都很常见。
当将实例转储到dict/JSON时,默认的键转换是camelCase,但这可以很容易地使用主数据类上提供的Meta配置来覆盖。
https://pypi.org/project/dataclass-wizard/
from dataclasses import dataclass
from dataclass_wizard import fromdict, asdict
@dataclass
class User:
name: str
age: int
is_active: bool
data = {
'name': 'John',
'age': 30,
'isActive': True,
}
user = fromdict(User, data)
assert user == User(name='John', age=30, is_active=True)
json_dict = asdict(user)
assert json_dict == {'name': 'John', 'age': 30, 'isActive': True}
设置元配置的例子,当序列化为dict/JSON时,将字段转换为lisp-case:
DumpMeta(key_transform='LISP').bind_to(User)
改进lovasoa非常好的答案。
如果你正在使用python 3.6+,你可以使用:
PIP安装棉花糖-enum和
PIP安装棉花糖数据类
它简单且类型安全。
你可以在string-json中转换你的类,反之亦然:
从对象到字符串Json:
from marshmallow_dataclass import dataclass
user = User("Danilo","50","RedBull",15,OrderStatus.CREATED)
user_json = User.Schema().dumps(user)
user_json_str = user_json.data
从String Json到Object:
json_str = '{"name":"Danilo", "orderId":"50", "productName":"RedBull", "quantity":15, "status":"Created"}'
user, err = User.Schema().loads(json_str)
print(user,flush=True)
类定义:
class OrderStatus(Enum):
CREATED = 'Created'
PENDING = 'Pending'
CONFIRMED = 'Confirmed'
FAILED = 'Failed'
@dataclass
class User:
def __init__(self, name, orderId, productName, quantity, status):
self.name = name
self.orderId = orderId
self.productName = productName
self.quantity = quantity
self.status = status
name: str
orderId: str
productName: str
quantity: int
status: OrderStatus
扩展一下DS的答案,如果你需要对象是可变的(而namedtuple不是),你可以使用记录类库而不是namedtuple:
import json
from recordclass import recordclass
data = '{"name": "John Smith", "hometown": {"name": "New York", "id": 123}}'
# Parse into a mutable object
x = json.loads(data, object_hook=lambda d: recordclass('X', d.keys())(*d.values()))
修改后的对象可以使用simplejson很容易地转换回json:
x.name = "John Doe"
new_json = simplejson.dumps(x)
查看JSON模块文档中的专门化JSON对象解码一节。您可以使用它将JSON对象解码为特定的Python类型。
这里有一个例子:
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) # -> <type 'type'>
更新
如果你想通过json模块访问字典中的数据,可以这样做:
user = json.loads('{"__type__": "User", "name": "John Smith", "username": "jsmith"}')
print user['name']
print user['username']
就像一本普通的字典。
Dacite也可能是您的解决方案,它支持以下功能:
嵌套结构
(基本)类型检查
可选字段(即typing.Optional)
工会
向前引用
集合
自定义类型钩子
https://pypi.org/project/dacite/
from dataclasses import dataclass
from dacite import from_dict
@dataclass
class User:
name: str
age: int
is_active: bool
data = {
'name': 'John',
'age': 30,
'is_active': True,
}
user = from_dict(data_class=User, data=data)
assert user == User(name='John', age=30, is_active=True)