Skip to the content.

Serializers

Serializers are DRF-style input/output adapters built on Pydantic. They validate incoming JSON and produce JSON-safe dicts for outgoing responses.

from axion.serializer import Serializer, SerializerValidationError

Output: serializing database rows

Declare a serializer and build it from a row:

class AddressSerializer(Serializer):
    street: str
    city: str
    postal_code: str


class UserSerializer(Serializer):
    id: int
    name: str
    email: str
    address: AddressSerializer
from services import get_user

user = get_user(1)
data = UserSerializer.from_row(user).data
response.json(data)

Use it from a route with dependency injection:

@app.route("/api/users/<int:user_id>")
def get_user(user_id: int, session: Session, response: Response):
    user = session.get(User, user_id)
    if user is None:
        response.send("User not found", 404)
        return
    response.json(UserSerializer.from_row(user).data)

Input: validating request bodies

Build a serializer from raw input and validate it:

class CreateUserSerializer(Serializer):
    name: str
    email: str
    age: int

    def validate_age(self, age: int) -> int:
        if age < 18:
            raise SerializerValidationError("Must be at least 18")
        return age


@app.route("/api/users", methods=["POST"])
def create_user(request: Request, response: Response):
    serializer = CreateUserSerializer.from_data(request.json)
    if not serializer.is_valid():
        response.json(serializer.errors, 400)
        return
    # serializer.validated_data is safe to use
    response.json(serializer.validated_data, 201)

Validation hooks

Nested serializers are validated recursively; field errors propagate into the parent’s errors under the nested field name.

Using serializers as handler parameters

Pydantic models (and serializers) can be declared directly as handler parameters. axion validates the JSON body against them and returns 400 automatically on failure:

from pydantic import BaseModel

from axion import WebServer
from axion.http import Response

app = WebServer(debug=True)


class CreateUser(BaseModel):
    name: str
    email: str


@app.route("/api/users", methods=["POST"])
def create_user(user: CreateUser, response: Response):
    response.json({"created": user.name}, 201)

Next steps