JSON¶
Json 解析¶
API 文档
pydantic.main.BaseModel.model_validate_json
pydantic.type_adapter.TypeAdapter.validate_json
pydantic_core.from_json
Pydantic 提供了内置的 JSON 解析功能,这有助于实现
- 显著的性能提升,而无需使用第三方库的成本
- 支持自定义错误
- 支持
strict
规范
这是一个 Pydantic 内置 JSON 解析的示例,通过 model_validate_json
方法展示了对 strict
规范的支持,同时解析与模型类型注解不匹配的 JSON 数据
from datetime import date
from pydantic import BaseModel, ConfigDict, ValidationError
class Event(BaseModel):
model_config = ConfigDict(strict=True)
when: date
where: tuple[int, int]
json_data = '{"when": "1987-01-28", "where": [51, -1]}'
print(Event.model_validate_json(json_data)) # (1)!
#> when=datetime.date(1987, 1, 28) where=(51, -1)
try:
Event.model_validate({'when': '1987-01-28', 'where': [51, -1]}) # (2)!
except ValidationError as e:
print(e)
"""
2 validation errors for Event
when
Input should be a valid date [type=date_type, input_value='1987-01-28', input_type=str]
where
Input should be a valid tuple [type=tuple_type, input_value=[51, -1], input_type=list]
"""
- JSON 没有
date
或元组类型,但 Pydantic 知道这一点,因此在直接解析 JSON 时允许字符串和数组作为输入。 - 如果您将相同的值传递给
model_validate
方法,Pydantic 将引发验证错误,因为启用了strict
配置。
在 v2.5.0 及更高版本中,Pydantic 使用 jiter
,一个快速且可迭代的 JSON 解析器来解析 JSON 数据。与 serde
相比,使用 jiter
带来了适度的性能提升,未来会变得更好。
jiter
JSON 解析器几乎完全兼容 serde
JSON 解析器,其中一个明显的增强功能是 jiter
支持反序列化 inf
和 NaN
值。在未来,jiter
旨在支持验证错误,以包含原始 JSON 输入中包含无效值的位置。
部分 JSON 解析¶
从 v2.7.0 开始,Pydantic 的 JSON 解析器 提供对部分 JSON 解析的支持,这通过 pydantic_core.from_json
公开。这是一个此功能在实际应用中的示例
from pydantic_core import from_json
partial_json_data = '["aa", "bb", "c' # (1)!
try:
result = from_json(partial_json_data, allow_partial=False)
except ValueError as e:
print(e) # (2)!
#> EOF while parsing a string at line 1 column 15
result = from_json(partial_json_data, allow_partial=True)
print(result) # (3)!
#> ['aa', 'bb']
- JSON 列表不完整 - 它缺少一个闭合的
"]
- 当
allow_partial
设置为False
(默认值)时,会发生解析错误。 - 当
allow_partial
设置为True
时,部分输入已成功反序列化。
这也适用于反序列化部分字典。例如
from pydantic_core import from_json
partial_dog_json = '{"breed": "lab", "name": "fluffy", "friends": ["buddy", "spot", "rufus"], "age'
dog_dict = from_json(partial_dog_json, allow_partial=True)
print(dog_dict)
#> {'breed': 'lab', 'name': 'fluffy', 'friends': ['buddy', 'spot', 'rufus']}
验证 LLM 输出
此功能对于验证 LLM 输出特别有益。我们撰写了一些关于此主题的博客文章,您可以在这里找到。
在未来版本的 Pydantic 中,我们希望通过 Pydantic 的其他 JSON 验证函数(pydantic.main.BaseModel.model_validate_json
和 pydantic.type_adapter.TypeAdapter.validate_json
)或模型配置来扩展对此功能的支持。敬请期待 🚀!
目前,您可以结合使用 pydantic_core.from_json
和 pydantic.main.BaseModel.model_validate
来实现相同的结果。这是一个例子
from pydantic_core import from_json
from pydantic import BaseModel
class Dog(BaseModel):
breed: str
name: str
friends: list
partial_dog_json = '{"breed": "lab", "name": "fluffy", "friends": ["buddy", "spot", "rufus"], "age'
dog = Dog.model_validate(from_json(partial_dog_json, allow_partial=True))
print(repr(dog))
#> Dog(breed='lab', name='fluffy', friends=['buddy', 'spot', 'rufus'])
提示
为了使部分 JSON 解析可靠地工作,模型上的所有字段都应具有默认值。
查看以下示例,以更深入地了解如何将默认值与部分 JSON 解析一起使用
将默认值与部分 JSON 解析一起使用
from typing import Annotated, Any, Optional
import pydantic_core
from pydantic import BaseModel, ValidationError, WrapValidator
def default_on_error(v, handler) -> Any:
"""
Raise a PydanticUseDefault exception if the value is missing.
This is useful for avoiding errors from partial
JSON preventing successful validation.
"""
try:
return handler(v)
except ValidationError as exc:
# there might be other types of errors resulting from partial JSON parsing
# that you allow here, feel free to customize as needed
if all(e['type'] == 'missing' for e in exc.errors()):
raise pydantic_core.PydanticUseDefault()
else:
raise
class NestedModel(BaseModel):
x: int
y: str
class MyModel(BaseModel):
foo: Optional[str] = None
bar: Annotated[
Optional[tuple[str, int]], WrapValidator(default_on_error)
] = None
nested: Annotated[
Optional[NestedModel], WrapValidator(default_on_error)
] = None
m = MyModel.model_validate(
pydantic_core.from_json('{"foo": "x", "bar": ["world",', allow_partial=True)
)
print(repr(m))
#> MyModel(foo='x', bar=None, nested=None)
m = MyModel.model_validate(
pydantic_core.from_json(
'{"foo": "x", "bar": ["world", 1], "nested": {"x":', allow_partial=True
)
)
print(repr(m))
#> MyModel(foo='x', bar=('world', 1), nested=None)
缓存字符串¶
从 v2.7.0 开始,Pydantic 的 JSON 解析器 提供对配置在 JSON 解析和验证期间如何缓存 Python 字符串的支持(当 Python 字符串从 Rust 字符串构造时,在 Python 验证期间,例如在 strip_whitespace=True
之后)。cache_strings
设置通过 模型配置 和 pydantic_core.from_json
公开。
cache_strings
设置可以采用以下任何值
True
或'all'
(默认值):缓存所有字符串'keys'
:仅缓存字典键,这仅适用于与pydantic_core.from_json
一起使用或在使用Json
解析 JSON 时False
或'none'
:不缓存
使用字符串缓存功能可以提高性能,但会略微增加内存使用量。
字符串缓存详细信息
- 字符串使用大小为 16,384 的全相联缓存进行缓存。
- 仅缓存
len(string) < 64
的字符串。 - 查找缓存有一些开销,这通常是为了避免构造字符串而值得的。但是,如果您知道数据中重复字符串很少,则可以通过使用
cache_strings=False
禁用此设置来获得性能提升。
JSON 序列化¶
API 文档
pydantic.main.BaseModel.model_dump_json
pydantic.type_adapter.TypeAdapter.dump_json
pydantic_core.to_json
有关 JSON 序列化的更多信息,请参阅序列化概念页面。