Перейти к содержанию

!!! предупреждение «🚧 В работе» Эта страница находится в стадии разработки.

JSON

Анализ Json

??? API «Документация по API» pydantic.main.BaseModel.model_validate_json pydantic.type_adapter.TypeAdapter.validate_json pydantic_core.from_json

Pydantic предоставляет встроенный анализ JSON, который помогает достичь:

  • Значительное повышение производительности без затрат на использование сторонней библиотеки.
  • Поддержка пользовательских ошибок
  • Поддержка strict спецификаций

Вот пример встроенного анализа JSON в Pydantic с помощью метода model_validate_json, демонстрирующий поддержку strict спецификаций при анализе данных JSON, которые не соответствуют аннотациям типа модели:

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, Pydantic выдаст ошибку проверки, поскольку включена strict конфигурация.

В версии 2.5.0 и выше Pydantic использует jiter — быстрый и повторяемый анализатор JSON для анализа данных JSON. Использование jiter по сравнению с serde приводит к небольшому улучшению производительности, которое в будущем станет еще лучше.

Анализатор JSON jiter почти полностью совместим с анализатором JSON serde , с одним заметным улучшением, заключающимся в том, что jiter поддерживает десериализацию значений inf и NaN . В будущем jiter предназначен для того, чтобы ошибки проверки поддержки включали в исходный входной файл JSON местоположение, содержащее недопустимое значение.

Частичный анализ JSON

Начиная с версии 2.7.0 , анализатор JSON Pydantic предлагает поддержку частичного анализа 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']
  1. Список JSON неполный — в нем отсутствует закрывающее "]
  2. Если для allow_partial установлено значение False (по умолчанию), возникает ошибка синтаксического анализа.
  3. Если для 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 мы планируем расширить поддержку этой функции за счет других функций проверки JSON Pydantic (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)
```

Кэширование строк

Начиная с версии 2.7.0 , анализатор JSON Pydantic предлагает поддержку настройки кэширования строк Python во время анализа и проверки JSON (когда строки 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' : кэширования нет.

Использование функции кэширования строк приводит к повышению производительности, но немного увеличивает использование памяти.

!!! обратите внимание «Подробности кэширования строк»

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 см. на странице «Основы сериализации» .


本文总阅读量