警告
“🚧 正在进行中” 此页面正在进行中。
JSON¶
Json Parsing¶
JSON 解析¶
API 文档
pydantic.main.BaseModel.model_validate_json
pydantic.type_adapter.TypeAdapter.validate_json
pydantic_core.from_json
Pydantic 提供了内置的 JSON 解析,这有助于实现:
-
显著的性能提升,无需使用第三方库的成本
-
支持自定义错误
-
对
strict
规范的支持
以下是通过 model_validate_json
方法使用 Pydantic 的内置 JSON 解析的示例,展示了在解析与模型的类型注解不匹配的 JSON 数据时对 strict
规范的支持:
from datetime import date
from typing import Tuple
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 数据。使用 jiter
与 serde
相比,性能有了适度的提高,未来还会更好。
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 Any, Optional, Tuple
import pydantic_core
from typing_extensions import Annotated
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 解析器提供了对配置 Python 字符串在 JSON 解析和验证期间如何缓存的支持(当 Python 字符串在 Python 验证期间从 Rust 字符串构建时,例如在 strip_whitespace=True
之后)。 cache_strings
设置通过 model config 和 pydantic_core.from_json
都暴露了出来。
cache_strings
设置可以取以下任何值:
-
True
或'all'
(默认):缓存所有字符串 -
'keys'
:仅缓存字典键,仅在与pydantic_core.from_json
一起使用或使用Json
解析 JSON 时适用 -
False
或'none'
:不缓存
使用字符串缓存功能会提高性能,但会略微增加内存使用量。
注意
“字符串缓存详细信息”
- Strings are cached using a fully associative cache with a size of 16,384.
- Only strings where
len(string) < 64
are cached. - There is some overhead to looking up the cache, which is normally worth it to avoid constructing strings.
However, if you know there will be very few repeated strings in your data, you might get a performance boost by disabling this setting with
cache_strings=False
.
JSON Serialization¶
JSON 序列化¶
pydantic.type_adapter.TypeAdapter.dump_json
有关 JSON 序列化的更多信息,请参阅序列化概念页面。
本文总阅读量次