コンテンツにスキップ

!!!警告「🚧 作業中」 このページは進行中です。

JSON

Json の解析

??? API "API ドキュメント" pydantic.main.BaseModel.model_validate_jsonpydantic.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]
    """
  1. JSON にはdateやタプル型がありませんが、Pydantic はそれを認識しているため、JSON を直接解析するときにそれぞれ文字列と配列を入力として許可します。
  2. 同じ値を model_validate メソッドに渡すと、 strict構成が有効になっているため、Pydantic は検証エラーを発生させます。

v2.5.0 以降では、Pydantic は、高速で反復可能な JSON パーサーであるjiter使用して JSON データを解析します。 serdeと比較してjiter使用すると、パフォーマンスが若干向上しますが、将来的にはさらに向上するでしょう。

jiter JSON パーサーはserde JSON パーサーとほぼ完全に互換性があり、注目すべき機能強化の 1 つは、 jiter infおよびNaN値の逆シリアル化をサポートしていることです。将来的には、 jiter無効な値を含む元の JSON 入力内の位置をサポート検証エラーに含めることができるようにすることを目的としています。

部分的な JSON 解析

v2.7.0 以降、Pydantic のJSON パーサーは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']
  1. JSON リストは不完全です - 終わりの"]がありません
  2. allow_partialFalse (デフォルト) に設定されている場合、解析エラーが発生します。
  3. allow_partialTrueに設定されている場合、入力の一部は正常に逆シリアル化されます。

これは、部分辞書の逆シリアル化にも機能します。例えば:

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 解析でのデフォルト値の使用」

```py
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 パーサーは、 JSON 解析および検証中に Python 文字列がキャッシュされる方法の構成のサポートを提供します (Python 検証中に、Python 文字列が Rust 文字列から構築されるとき、たとえば、 strip_whitespace=Trueの後)。 cache_strings設定は、model configpydantic_core.from_json の両方を介して公開されます。

cache_strings設定には、次のいずれかの値を指定できます。

  • Trueまたは'all' (デフォルト): すべての文字列をキャッシュします。
  • 'keys' : 辞書キーのみをキャッシュします。これは、pydantic_core.from_json で使用される場合、または Json を使用して JSON を解析する場合にのみ適用されます。
  • Falseまたは'none' : キャッシュなし

文字列キャッシュ機能を使用するとパフォーマンスが向上しますが、メモリ使用量がわずかに増加します。

!!! note「文字列キャッシュの詳細」

1. Strings are cached using a fully associative cache with a size of
[16,384](https://github.com/pydantic/jiter/blob/5bbdcfd22882b7b286416b22f74abd549c7b2fd7/src/py_string_cache.rs#L113).
2. Only strings where `len(string) < 64` are cached.
3. 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シリアル化

??? API「APIドキュメント」 pydantic.main.BaseModel.model_dump_json
pydantic.type_adapter.TypeAdapter.dump_json
pydantic_core.to_json

JSON シリアル化の詳細については、 「シリアル化の概念」ページを参照してください。


本文总阅读量