Sai*_*hna 242 python django json
我想使用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()
Run Code Online (Sandbox Code Playgroud)
这工作正常,但我如何处理复杂的JSON数据对象?
如果我能以某种方式将这个JSON对象转换为Python对象以便于使用,那会不会更好?
DS.*_*DS. 315
你可以在一行中使用namedtuple和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
Run Code Online (Sandbox Code Playgroud)
或者,轻松地重复使用:
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)
Run Code Online (Sandbox Code Playgroud)
如果你希望它处理的是不好的属性名称键,检查出namedtuple的rename参数.
Sha*_*kai 119
检查出标题为专业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'>
Run Code Online (Sandbox Code Playgroud)
更新
如果要通过json模块访问字典中的数据,请执行以下操作:
user = json.loads('{"__type__": "User", "name": "John Smith", "username": "jsmith"}')
print user['name']
print user['username']
Run Code Online (Sandbox Code Playgroud)
就像一本普通的字典.
edd*_*eek 86
这不是代码高尔夫,但这是我最短的技巧,types.SimpleNamespace用作JSON对象的容器.
与领先的namedtuple解决方案相比,它是:
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)
Run Code Online (Sandbox Code Playgroud)
cma*_*nda 75
你可以试试这个:
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)
Run Code Online (Sandbox Code Playgroud)
只需创建一个新的Object,并将参数作为映射传递.
ube*_*kel 34
这是一个快速而又脏的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()
Run Code Online (Sandbox Code Playgroud)
spu*_*kus 16
对于复杂对象,您可以使用JSON Pickle
用于将任意对象图序列化为JSON的Python库.它几乎可以占用任何Python对象并将对象转换为JSON.此外,它可以将对象重新构建回Python.
lov*_*soa 10
如果您使用的是 python 3.6+,则可以使用marshmallow-dataclass。与上面列出的所有解决方案相反,它既简单又类型安全:
from marshmallow_dataclass import dataclass
@dataclass
class User:
name: str
user = User.Schema().load({"name": "Ramirez"})
Run Code Online (Sandbox Code Playgroud)
由于没有人提供像我一样的答案,我将把它发布在这里。
它是一个强大的类,可以轻松地在 JSON 之间来回转换str,dict我已经从另一个问题的答案中复制了它:
import json
class PyJSON(object):
def __init__(self, d):
if type(d) is str:
d = json.loads(d)
self.from_dict(d)
def from_dict(self, d):
self.__dict__ = {}
for key, value in d.items():
if type(value) is dict:
value = PyJSON(value)
self.__dict__[key] = value
def to_dict(self):
d = {}
for key, value in self.__dict__.items():
if type(value) is PyJSON:
value = value.to_dict()
d[key] = value
return d
def __repr__(self):
return str(self.to_dict())
def __setitem__(self, key, value):
self.__dict__[key] = value
def __getitem__(self, key):
return self.__dict__[key]
json_str = """... JSON string ..."""
py_json = PyJSON(json_str)
Run Code Online (Sandbox Code Playgroud)
改进 lovasoa 的非常好的答案。
如果您使用的是 python 3.6+,则可以使用:
pip install marshmallow-enum和
pip install marshmallow-dataclass
它简单且类型安全。
您可以在 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
Run Code Online (Sandbox Code Playgroud)
从字符串 Json 到对象:
json_str = '{"name":"Danilo", "orderId":"50", "productName":"RedBull", "quantity":15, "status":"Created"}'
user, err = User.Schema().loads(json_str)
print(user,flush=True)
Run Code Online (Sandbox Code Playgroud)
类定义:
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
Run Code Online (Sandbox Code Playgroud)
如果您使用的是Python 3.5+,则可以jsons用来序列化和反序列化为普通的旧Python对象:
import jsons
response = request.POST
# You'll need your class attributes to match your dict keys, so in your case do:
response['id'] = response.pop('user_id')
# Then you can load that dict into your class:
user = jsons.load(response, FbApiUser)
user.save()
Run Code Online (Sandbox Code Playgroud)
您还可以FbApiUser从继承继承以jsons.JsonSerializable获取更多的优雅:
user = FbApiUser.from_json(response)
Run Code Online (Sandbox Code Playgroud)
如果您的类由Python默认类型(例如字符串,整数,列表,日期时间等)组成,则这些示例将起作用。但是,jsonslib将需要自定义类型的类型提示。
英安岩也可能是您的解决方案,它支持以下功能:
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)
Run Code Online (Sandbox Code Playgroud)
以下代码以递归方式使用对象键创建动态属性。
JSON 对象 - fb_data.json:
{
"name": "John Smith",
"hometown": {
"name": "New York",
"id": 123
},
"list": [
"a",
"b",
"c",
1,
{
"key": 1
}
],
"object": {
"key": {
"key": 1
}
}
}
Run Code Online (Sandbox Code Playgroud)
关于转换我们有3种情况:
import json
class AppConfiguration(object):
def __init__(self, data=None):
if data is None:
with open("fb_data.json") as fh:
data = json.loads(fh.read())
else:
data = dict(data)
for key, val in data.items():
setattr(self, key, self.compute_attr_value(val))
def compute_attr_value(self, value):
if isinstance(value, list):
return [self.compute_attr_value(x) for x in value]
elif isinstance(value, dict):
return AppConfiguration(value)
else:
return value
if __name__ == "__main__":
instance = AppConfiguration()
print(instance.name)
print(instance.hometown.name)
print(instance.hometown.id)
print(instance.list[4].key)
print(instance.object.key.key)
Run Code Online (Sandbox Code Playgroud)
现在键、值对是属性 - 对象。
输出:
John Smith
New York
123
1
1
Run Code Online (Sandbox Code Playgroud)
支持TypeScript、、、、、、、、、、、、、、、、、、和。PythonGoRubyC#JavaSwiftRustKotlinC++FlowObjective-CJavaScriptElmJSON Schema
quicktype从示例 JSON 数据推断类型,然后输出强类型模型和序列化器,以便以所需的编程语言处理该数据。
输出:
# Generated by https://quicktype.io
#
# To change quicktype's target language, run command:
#
# "Set quicktype target language"
from typing import List, Union
class Hometown:
name: str
id: int
def __init__(self, name: str, id: int) -> None:
self.name = name
self.id = id
class Key:
key: int
def __init__(self, key: int) -> None:
self.key = key
class Object:
key: Key
def __init__(self, key: Key) -> None:
self.key = key
class FbData:
name: str
hometown: Hometown
list: List[Union[Key, int, str]]
object: Object
def __init__(self, name: str, hometown: Hometown, list: List[Union[Key, int, str]], object: Object) -> None:
self.name = name
self.hometown = hometown
self.list = list
self.object = object
Run Code Online (Sandbox Code Playgroud)
此扩展可在Visual Studio Code Marketplace中免费获得。
我认为最轻的解决方案是
\nimport orjson # faster then json =)\nfrom typing import NamedTuple\n\n_j = \'{"name":"\xd0\x98\xd0\xb2\xd0\xb0\xd0\xbd","age":37,"mother":{"name":"\xd0\x9e\xd0\xbb\xd1\x8c\xd0\xb3\xd0\xb0","age":58},"children":["\xd0\x9c\xd0\xb0\xd1\x88\xd0\xb0","\xd0\x98\xd0\xb3\xd0\xbe\xd1\x80\xd1\x8c","\xd0\xa2\xd0\xb0\xd0\xbd\xd1\x8f"],"married": true,\' \\\n \'"dog":null} \'\n\n\nclass PersonNameAge(NamedTuple):\n name: str\n age: int\n\n\nclass UserInfo(NamedTuple):\n name: str\n age: int\n mother: PersonNameAge\n children: list\n married: bool\n dog: str\n\n\nj = orjson.loads(_j)\nu = UserInfo(**j)\n\nprint(u.name, u.age, u.mother, u.children, u.married, u.dog)\n\n>>> Ivan 37 {\'name\': \'Olga\', \'age\': 58} [\'Mary\', \'Igor\', \'Jane\'] True None\nRun Code Online (Sandbox Code Playgroud)\n
如果您正在寻找 JSON 或任何复杂字典的类型安全反序列化到 Python 类中,我强烈推荐Python 3.7+ 的pydantic 。它不仅具有简洁的 API(不需要编写“帮助程序”样板),可以与 Python数据类集成,而且具有复杂和嵌套数据结构的静态和运行时类型验证。
用法示例:
from pydantic import BaseModel
from datetime import datetime
class Item(BaseModel):
field1: str | int # union
field2: int | None = None # optional
field3: str = 'default' # default values
class User(BaseModel):
name: str | None = None
username: str
created: datetime # default type converters
items: list[Item] = [] # nested complex types
data = {
'name': 'Jane Doe',
'username': 'user1',
'created': '2020-12-31T23:59:00+10:00',
'items': [
{'field1': 1, 'field2': 2},
{'field1': 'b'},
{'field1': 'c', 'field3': 'override'}
]
}
user: User = User(**data)
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息和功能,请查看 pydantic文档中的有理部分。
| 归档时间: |
|
| 查看次数: |
361922 次 |
| 最近记录: |