hag*_*aiw 34 python python-dataclasses pydantic
我正在将dataclasses项目中现有的转换为pydantic-dataclasses,我使用这些dataclasses来表示我需要编码和解析 json 的模型。
这是我当前方法的一个示例,该方法对于我的用例来说不够好,我有一个类A,我想将其转换为字典(稍后转换为 json)并从该字典中读取。但我能找到的将 json 解析回模型的唯一方法给了我底层BaseModel而不是dataclass.
请注意,我使用该asdict函数将 a 转换dataclass为 a dict,因为它是用来pydantic_encoder将 a 转换dataclass为 json 的,并使用pydantic_encoder文档建议的将 a 转换pydantic-dataclass为 json:
https: //pydantic-docs.helpmanual.io/usage /数据类/
from dataclasses import asdict
from pydantic.dataclasses import dataclass
from pydantic import BaseModel
@dataclass
class A:
x: str
a = A("string")
a_dict = asdict(a)
parsed_a = A.__pydantic_model__.parse_obj(a_dict)
print(f"type of a: {type(a)}")
print(f"type of parsed_a: {type(parsed_a)}")
print(f"a is instance of A: {isinstance(a, A)}")
print(f"parsed_a is instance of A: {isinstance(parsed_a, A)}")
print(f"a is instance of BaseModel: {isinstance(a, BaseModel)}")
print(f"parsed_a is instance of BaseModel: {isinstance(parsed_a, BaseModel)}")
Run Code Online (Sandbox Code Playgroud)
输出:
type of a: <class '__main__.A'>
type of parsed_a: <class '__main__.A'>
a is instance of A: True
parsed_a is instance of A: False
a is instance of BaseModel: False
parsed_a is instance of BaseModel: True
Run Code Online (Sandbox Code Playgroud)
有没有办法A从解析的初始化BaseModel?
Gui*_*lem 26
我想我来晚了一点,但我认为这个答案对于未来有同样问题的用户来说可能会很方便。
要将其转换dataclass为 json,您可以使用已经使用的组合(asdict加号json.dump)。
from pydantic.dataclasses import dataclass
@dataclass
class User:
id: int
name: str
user = User(id=123, name="James")
d = asdict(user) # {'id': 123, 'name': 'James'
user_json = json.dumps(d)
print(user_json) # '{"id": 123, "name": "James"}'
# Or directly with pydantic_encoder
json.dumps(user, default=pydantic_encoder)
Run Code Online (Sandbox Code Playgroud)
然后从原始中json你可以使用 aBaseModel和parse_raw方法。
如果你想将 json 反序列化为pydantic实例,我建议你使用以下parse_raw方法:
user = User.__pydantic_model__.parse_raw('{"id": 123, "name": "James"}')
print(user)
# id=123 name='James'
Run Code Online (Sandbox Code Playgroud)
否则,如果您想保留数据类:
json_raw = '{"id": 123, "name": "James"}'
user_dict = json.loads(json_raw)
user = User(**user_dict)
Run Code Online (Sandbox Code Playgroud)
pce*_*con 11
我认为现在可以通过简单的方式解决这个问题。添加到@Guillem示例:
from pydantic.dataclasses import dataclass
from pydantic.tools import parse_obj_as
import dataclasses
import json
@dataclass
class User:
id: int
name: str
user = User(id=123, name="James")
user_json = json.dumps(dataclasses.asdict(user))
print(user_json) # '{"id": 123, "name": "James"}'
user_dict = json.loads(user_json)
user = parse_obj_as(User, user_dict)
print(user) # User(id=123, name='James')
Run Code Online (Sandbox Code Playgroud)
它也适用于递归。
小智 8
Pydantic建议使用parse_raw反序列化 JSON 字符串。
from pydantic import BaseModel
class ResponseData(BaseModel):
status_code: int
text: str
reason: str
class Config:
orm_mode = True
Run Code Online (Sandbox Code Playgroud)
x = ResponseData(status_code=200, text="", reason="")
json = x.json()
response = ResponseData.parse_raw(json)
assert x == response
print(response.dict())
Run Code Online (Sandbox Code Playgroud)
为了建立在其他人的答案的基础上,因为正确/最佳的答案似乎不断变化:
使用 PydanticTypeAdapter是目前的最佳选择。更新了@pceccon 示例:
from pydantic.dataclasses import dataclass
from pydantic import TypeAdapter
import dataclasses
import json
@dataclass
class User:
id: int
name: str
user = User(id=123, name="James")
user_json = json.dumps(dataclasses.asdict(user))
print(user_json) # '{"id": 123, "name": "James"}'
user = TypeAdapter(User).validate_json(user_json)
print(user) # User(id=123, name='James')
print(user.name) # 'James'
Run Code Online (Sandbox Code Playgroud)
如果您希望 PyCharm(或任何编辑器)为您提供自动完成/智能感知,请使用类型提示:
user: User = TypeAdapter(User).validate_json(user_json)
Run Code Online (Sandbox Code Playgroud)
如果你有字典而不是 json,你可以使用TypeAdapter.validate_python:
user: User = TypeAdapter(User).validate_python(user_dict)
Run Code Online (Sandbox Code Playgroud)
这对于您的模型/类定义递归地起作用。
| 归档时间: |
|
| 查看次数: |
61453 次 |
| 最近记录: |