Browse Source

Add custom GenerateJsonSchema

feat/custom-generate-json-schema
Marcelo Trylesinski 2 years ago
parent
commit
9df629721b
  1. 70
      fastapi/_compat.py
  2. 2
      fastapi/params.py

70
fastapi/_compat.py

@ -44,8 +44,10 @@ sequence_annotation_to_type = {
sequence_types = tuple(sequence_annotation_to_type.keys()) sequence_types = tuple(sequence_annotation_to_type.keys())
if PYDANTIC_V2: if PYDANTIC_V2:
from typing import Sequence
from pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationError from pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationError
from pydantic import TypeAdapter from pydantic import PydanticUserError, TypeAdapter
from pydantic import ValidationError as ValidationError from pydantic import ValidationError as ValidationError
from pydantic._internal._schema_generation_shared import ( # type: ignore[attr-defined] from pydantic._internal._schema_generation_shared import ( # type: ignore[attr-defined]
GetJsonSchemaHandler as GetJsonSchemaHandler, GetJsonSchemaHandler as GetJsonSchemaHandler,
@ -53,16 +55,78 @@ if PYDANTIC_V2:
from pydantic._internal._typing_extra import eval_type_lenient from pydantic._internal._typing_extra import eval_type_lenient
from pydantic._internal._utils import lenient_issubclass as lenient_issubclass from pydantic._internal._utils import lenient_issubclass as lenient_issubclass
from pydantic.fields import FieldInfo from pydantic.fields import FieldInfo
from pydantic.json_schema import GenerateJsonSchema as GenerateJsonSchema from pydantic.json_schema import (
DEFAULT_REF_TEMPLATE,
DefsRef,
JsonSchemaKeyT,
JsonSchemaMode,
_sort_json_schema,
)
from pydantic.json_schema import GenerateJsonSchema as _GenerateJsonSchema
from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue
from pydantic_core import CoreSchema as CoreSchema from pydantic_core import CoreSchema as CoreSchema
from pydantic_core import MultiHostUrl as MultiHostUrl from pydantic_core import MultiHostUrl as MultiHostUrl
from pydantic_core import PydanticUndefined, PydanticUndefinedType from pydantic_core import PydanticUndefined, PydanticUndefinedType, core_schema
from pydantic_core import Url as Url from pydantic_core import Url as Url
from pydantic_core.core_schema import ( from pydantic_core.core_schema import (
general_plain_validator_function as general_plain_validator_function, general_plain_validator_function as general_plain_validator_function,
) )
class GenerateJsonSchema(_GenerateJsonSchema):
def __init__(
self, by_alias: bool = True, ref_template: str = DEFAULT_REF_TEMPLATE
):
super().__init__(by_alias=by_alias, ref_template=ref_template)
self.skip_null_schema = False
def nullable_schema(
self, schema: core_schema.NullableSchema
) -> JsonSchemaValue:
if self.skip_null_schema:
return super().generate_inner(schema["schema"])
return super().nullable_schema(schema)
def generate_definitions(
self,
inputs: Sequence[
tuple[JsonSchemaKeyT, JsonSchemaMode, core_schema.CoreSchema]
],
) -> tuple[
dict[tuple[JsonSchemaKeyT, JsonSchemaMode], JsonSchemaValue],
dict[DefsRef, JsonSchemaValue],
]:
# Avoid circular import - Maybe there's a better way to check if it's a Param
from fastapi.params import Param
if self._used:
raise PydanticUserError(
"This JSON schema generator has already been used to generate a JSON schema. "
f"You must create a new instance of {type(self).__name__} to generate a new JSON schema.",
code="json-schema-already-used",
)
for key, mode, schema in inputs:
self.mode = mode
self.skip_null_schema = isinstance(key, ModelField) and isinstance(
key.field_info, Param
)
self.generate_inner(schema)
definitions_remapping = self._build_definitions_remapping()
json_schemas_map: dict[tuple[JsonSchemaKeyT, JsonSchemaMode], DefsRef] = {}
for key, mode, schema in inputs:
self.mode = mode
json_schema = self.generate_inner(schema)
json_schemas_map[(key, mode)] = definitions_remapping.remap_json_schema(
json_schema
)
json_schema = {"$defs": self.definitions}
json_schema = definitions_remapping.remap_json_schema(json_schema)
self._used = True
return json_schemas_map, _sort_json_schema(json_schema["$defs"]) # type: ignore
Required = PydanticUndefined Required = PydanticUndefined
Undefined = PydanticUndefined Undefined = PydanticUndefined
UndefinedType = PydanticUndefinedType UndefinedType = PydanticUndefinedType

2
fastapi/params.py

@ -98,7 +98,7 @@ class Param(FieldInfo):
kwargs["examples"] = examples kwargs["examples"] = examples
if regex is not None: if regex is not None:
warnings.warn( warnings.warn(
"`regex` has been depreacated, please use `pattern` instead", "`regex` has been deprecated, please use `pattern` instead",
category=DeprecationWarning, category=DeprecationWarning,
stacklevel=4, stacklevel=4,
) )

Loading…
Cancel
Save