Saltar a contenido

JSON Schema

La clase ValidateSchema de Callisto, ubicada en /app/common/middlewares/json_schema.py contiene una implementación del validadador de JSON Schema 2020-12 que permite validar el cuerpo de la petición (el request body y usualmente en formato json).

consulta el middleware:

y el apartado de:

La clase ValidateSchema, es utilizada aquí como Inyección de Depedencias, para obtener el cuerpo de la peticion, validarlo con JSONSchema v. draft 2020-12, y utilizarlo dentro de una vista (view).

veamos un ejemplo:

definimos un esquema para validar la entrada de datos:

Importante

Recuerda que el esquema debe estar bajo draft 2020-12.

create_city_scheme = {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "title": "Core schema for Cities",
    "description": "schema to create new cities",
    "properties": {"data": {"description": "main data", "$ref": "#/definitions/data"}},
    "additionalProperties": False,
    "required": ["data"],
    "definitions": {
        "data": {
            "type": "array",
            "title": "City info",
            "minItems": 1,
            "items": {
                "type": "object",
                "minProperties": 3,
                "properties": {
                    "name": {"type": "string", "minLength": 2, "maxLength": 120},
                    "code": {"type": "string", "minLength": 2, "maxLength": 7},
                    "state_id": {"type": "string", "minLength": 30, "maxLength": 32},
                },
                "additionalProperties": False,
                "required": ["name", "code", "state_id"],
            },
        }
    },
}

importamos ValidateSchema para utilizarlo en nuestro route:

from app.common.middlewares.json_schema import ValidateSchema

utilizamos una dependencia(Depends) en nuestro route, para realizar la validación del cuerpo de la petición:

1
2
3
...

body: dict[str, Any] = Depends(ValidateSchema(create_city_scheme)),

Nota

Si la validación es exitosa, se retorna un objeto JSON (cuerpo de la petición) y no un objeto de Pydantic.

utiliza el objeto JSON, dentro del route:

1
2
3
...

logger.info("create body: {}", body)

Ejemplo

A continuación el ejemplo completo:

from app.common.middlewares.json_schema import ValidateSchema
from app.modules.cities.schemas.cities_schema import create_city_scheme
...

@cities_router.post("/create")
async def cities_create(
    request: Request,
    body: dict[str, Any] = Depends(ValidateSchema(create_city_scheme)),
):
    """Esta función de ApiRouter explica como usar el middleware de
    `ValidateSchema`, para validar JSON Schema.
    """

    try:
        logger.info("create request: {}", request)
        logger.info("create body: {}", body)

        data: dict[str, Any] = body.get("data")

        return response(201, HTTPStatus.CREATED, data)
    except Exception as e:
        logger.exception("cities_router.post cities_create Exception: {}", e)
        return response(400, HTTPStatus.UNEXPECTED_ERROR, error=str(e))

Recuerda

ValidateSchema solo está disponible para métodos POST y PUT.

cuando se valida el cuerpo de la petición:

  • Si ocurre un error en la validación, se generará una excepción de tipo HTTPException para devolver respuestas HTTP con errores al cliente.
  • Si la validación es exitosa, se retorna un objeto JSON (cuerpo de la petición) y no un objeto de Pydantic.

Lectura recomendada