When building Symfony APIs, I kept duplicating the same request contract:
- validation rules in a DTO
- OpenAPI schema (often separately)
- mapping / glue code around it
After enough endpoints, the API layer started feeling heavier than the business logic.
Hereβs a tiny example (validation in a DTO):
class CreateUserRequest
{
#[Assert\NotBlank]
#[Assert\Email]
public string $email;
}
The same email then needs to exist again in OpenAPI docs - and the two drift over time.
So I built a small Symfony bundle to reduce that duplication.
Instead of describing the request multiple times, I keep a single JSON Schema:
{
"type": "object",
"required": ["email"],
"properties": {
"email": {
"type": "string",
"format": "email"
}
}
}
That schema becomes the source of truth for:
- request validation
- request mapping
- OpenAPI generation
Basic usage:
#[MapRequest('schemas/user-create.json')]
UserCreateDto $user
It's not trying to replace Symfony (or API Platform). The goal is to adopt it gradually and write less boilerplate while keeping request contracts explicit.
Project: https://github.com/outcomer/symfony-json-schema-validation
Docs: https://outcomer.github.io/symfony-json-schema-validation/
What part do you duplicate the most in Symfony APIs: validation, OpenAPI, or mapping?
Top comments (0)