When you build an API, the first line of defense isn't your firewall or your database — it's the request itself. Every payload that hits your controller is untrusted until proven otherwise. Yet a surprising number of production APIs still rely on manual json_decode() calls and scattered if checks, which is fragile, hard to maintain, and easy to bypass.

This article walks through the modern, "senior-level" approach to request validation in Symfony 7, and clarifies a point that's often misunderstood: where XSS protection actually belongs.

The Symfony Way: DTO + Validator + MapRequestPayload

Since Symfony 6.3, the #[MapRequestPayload] attribute lets you deserialize and validate a JSON body in one step, using a dedicated Data Transfer Object

Step 1 — Define the shape of the request: