Ga naar inhoud

!!! waarschuwing "🚧 Work in Progress" Deze pagina is work in progress.

JSON

Json-parsering

??? api "API-documentatie" pydantic.main.BaseModel.model_validate_json pydantic.type_adapter.TypeAdapter.validate_json pydantic_core.from_json

Pydantic biedt ingebouwde JSON-parsing, wat helpt bij het bereiken van:

  • Aanzienlijke prestatieverbeteringen zonder de kosten van het gebruik van een bibliotheek van derden
  • Ondersteuning voor aangepaste fouten
  • Ondersteuning voor strict specificaties

Hier is een voorbeeld van de ingebouwde JSON-parsering van Pydantic via de model_validate_json methode, waarin de ondersteuning voor strict specificaties wordt getoond tijdens het parseren van JSON-gegevens die niet overeenkomen met de typeannotaties van het model:

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 heeft geen date of tuple-typen, maar Pydantic weet dat dit dus strings en arrays als invoer toestaat bij het rechtstreeks parseren van JSON.
  2. Als u dezelfde waarden doorgeeft aan de methode model_validate, zal Pydantic een validatiefout genereren omdat de strict configuratie is ingeschakeld.

In v2.5.0 en hoger gebruikt Pydantic jiter , een snelle en iterabele JSON-parser, om JSON-gegevens te parseren. Het gebruik van jiter in vergelijking met serde resulteert in bescheiden prestatieverbeteringen die in de toekomst nog beter zullen worden.

De jiter JSON-parser is bijna volledig compatibel met de serde JSON-parser, met als opvallende verbetering dat jiter deserialisatie van inf en NaN -waarden ondersteunt. In de toekomst is jiter bedoeld om ondersteuningsvalidatiefouten mogelijk te maken om de locatie op te nemen in de oorspronkelijke JSON-invoer die de ongeldige waarde bevatte.

Gedeeltelijke JSON-parsering

Vanaf v2.7.0 biedt de JSON-parser van Pydantic ondersteuning voor gedeeltelijke JSON-parsering, die wordt weergegeven via pydantic_core.from_json. Hier is een voorbeeld van deze functie in actie:

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. De JSON-lijst is onvolledig - er ontbreekt een afsluiting "]
  2. Wanneer allow_partial is ingesteld op False (de standaardinstelling), treedt er een parseerfout op.
  3. Wanneer allow_partial is ingesteld op True , wordt een deel van de invoer met succes gedeserialiseerd.

Dit werkt ook voor het deserialiseren van gedeeltelijke woordenboeken. Bijvoorbeeld:

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']}

!!! tip " LLM uitvoer valideren" Deze functie is vooral nuttig voor het valideren van LLM uitvoer. We hebben een aantal blogposts over dit onderwerp geschreven, die je hier kunt vinden.

In toekomstige versies van Pydantic verwachten we de ondersteuning voor deze functie uit te breiden via de andere JSON-validatiefuncties van Pydantic (pydantic.main.BaseModel.model_validate_json en pydantic.type_adapter.TypeAdapter.validate_json) of modelconfiguratie. Blijf op de hoogte 🚀!

Voorlopig kun je pydantic_core.from_json gebruiken in combinatie met pydantic.main.BaseModel.model_validate om hetzelfde resultaat te bereiken. Hier is een voorbeeld:

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 Om gedeeltelijke JSON-parsering betrouwbaar te laten werken, moeten alle velden in het model standaardwaarden hebben.

Bekijk het volgende voorbeeld voor een meer diepgaande blik op het gebruik van standaardwaarden met gedeeltelijke JSON-parsering:

!!! voorbeeld 'Standaardwaarden gebruiken met gedeeltelijke JSON-parsering'

```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)
```

Caching van tekenreeksen

Vanaf v2.7.0 biedt de JSON-parser van Pydantic ondersteuning voor het configureren van hoe Python-strings in de cache worden opgeslagen tijdens JSON-parsering en -validatie (wanneer Python-strings worden opgebouwd uit Rust-strings tijdens Python-validatie, bijvoorbeeld na strip_whitespace=True ). De instelling cache_strings wordt weergegeven via zowel model config als pydantic_core.from_json.

De instelling cache_strings kan een van de volgende waarden aannemen:

  • True of 'all' (de standaard): cache alle strings
  • 'keys' : cache alleen woordenboeksleutels, dit is alleen van toepassing bij gebruik met pydantic_core.from_json of bij het parseren van JSON met behulp van Json
  • False of 'none' : geen caching

Het gebruik van de tekenreekscachefunctie resulteert in prestatieverbeteringen, maar verhoogt het geheugengebruik enigszins.

String Caching Details

  1. Strings are cached using a fully associative cache with a size of 16,384.
  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-serialisatie

??? api "API-documentatie" pydantic.main.BaseModel.model_dump_json
pydantic.type_adapter.TypeAdapter.dump_json
pydantic_core.to_json

Zie de pagina Serialisatieconcepten voor meer informatie over JSON-serialisatie.


本文总阅读量