JSON¶
🚧 Work in Progress
This page is a work in progress.
このページは、翻訳時点(2024/08)では本家では作成途中です。
Json Parsing¶
API Documentation
pydantic.main.BaseModel.model_validate_json
pydantic.type_adapter.TypeAdapter.validate_json
pydantic_core.from_json
Pydanticは組み込みのJSON解析を提供し、次のことを実現するのに役立ちます。
- サードパーティ製ライブラリを使用せずに、パフォーマンスが大幅に向上
- カスタムエラーのサポート
- "厳密な"仕様のサポート
以下は、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
メソッドに渡した場合、strict
設定が有効になっているため、Pydanticは検証エラーを発生します。
v2.5.0以降では、Pydanticは高速で反復可能なJSONパーサーであるjiter
を使用してJSONデータを解析します。
serde
と比較してjeter
を使用すると、将来さらに良くなるであろう適度なパフォーマンスの改善が得られます。
jeter
JSONパーサーはserde
JSONパーサーとほぼ完全に互換性がありますが、注目すべき改良点の1つはjeter
がinf
値とNaN
値のデシリアライズをサポートしていることです。
将来、jeter
は、サポート検証エラーが、無効な値を含む元のJSON入力内の場所を含むことを可能にすることを意図しています。
Partial JSON Parsing¶
v2.7.0から、PydanticのJSON parserは、pydantic_core.from_json
で公開されている部分的な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']}
Validating LLM Output
この機能は、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'])
Tip
部分的なJSON解析が確実に動作するためには、モデル上のすべてのフィールドにデフォルト値が必要です。
部分的なJSON解析でデフォルト値を使用する方法の詳細については、次の例を参照してください。
Using default values with partial JSON parsing
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)
Caching Strings¶
v2.7.0から、PydanticのJSONパーサは、JSONの解析と検証中にPython文字列をキャッシュする方法の設定をサポートしています(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'
: キャッシュしない
文字列キャッシング機能を使用すると、パフォーマンスが向上しますが、メモリ使用量が若干増加します。
String Caching Details
1. 文字列は、サイズ16,384のフルアソシアティブ方式を使用してキャッシュされます。
2. len(string)<64
の文字列のみがキャッシュされます。
3. キャッシュの検索には多少のオーバーヘッドがありますが、これは通常、文字列の構築を避けるために行う価値があります。ただし、データ内に繰り返される文字列がほとんどないことがわかっている場合は、cache_strings=False
でこの設定を無効にすることでパフォーマンスが向上する可能性があります。
JSON Serialization¶
API Documentation
pydantic.main.BaseModel.model_dump_json
pydantic.type_adapter.TypeAdapter.dump_json
pydantic_core.to_json
JSONシリアライゼーションの詳細については、Serialization Conceptsページを参照してください。