1. Intro
First, let’s clarify a bit how the Request/Response architecture works when using REST APIs (if you don’t know what this means – you might be in the wrong place 🙂).
A client sends a request like this:
The server receives the request… then ??? happens, and the server replies:
What’s this ??? part, you ask?
This is where Symfony Serializer comes in. The backend receives a JSON request from a mobile or frontend app. It converts that JSON into something it can understand – in our case, a PHP object.
Once the backend understands it, it can save it to the database (or do whatever the business logic dictates). If saving, the object gets an ID and some timestamps. Then the Serializer converts it back to JSON and returns it to the frontend/mobile app as a response — and boom 💥 the Request/Response cycle is complete.
2. Serializer
2.1 What the hell is it?
It’s a Symfony component (duh). We’ll show some cool thingies you can do with it.
Main features:
-
Object → JSON — serialize
-
JSON → Object — deserialize
-
Object → array — normalize
-
Array → Object — denormalize
-
Array → JSON — encode
-
JSON → array — decode
We’ll focus on the first two since they’re the most used ones for REST APIs.
2.2 How do I install and use it?
As always in PHP – install it via Composer:
Then use Symfony’s autowiring:
Or build it manually (not recommended for prod but useful for examples):
2.3 What about the other way around?
Let’s do a reverse example: deserialize JSON to a Genre class object.
JSON input:
PHP class:
Deserialization:
Simple, right? Best thing is – we can tweak it to our liking.
2.4 Groups
Groups help with:
-
controlling what properties to include during conversion
-
controlling what properties to validate (yep, Validator understands groups too!)
Say we have a User object like this:
When creating a user, we want to hash the password before saving, and not return the password to the frontend. Groups help us do that.
Let’s namespace our groups using the {object}:{action} format:
-
Use user:create for incoming data
-
Use user:read when returning data (without password)
2.5 Virtual Properties
Let’s say our frontend doesn’t want to concatenate first and last name — they want fullName as a separate field.
Be smart. Use a virtual property:
When serializing with the user:read group — you'll get fullName too!
Example 2: Book + Author listing
Book.php
Author.php
When serializing with group book:listing, you’ll get just: book id, name, and author name. Perfect for list views.
2.6 NameConverters
By default, Serializer uses property names as-is. So:
…become:
But if your frontend expects snake_case, use a name converter!
In your framework.yaml:
Now this:
…becomes:
You can also create your own custom NameConverter if needed.
2.7 Other formats
Of course, it’s not just JSON — it supports:
-
CSV
-
XML
-
YAML
-
and our queen 👑 — JSON
Feel free to explore the others on your own!
Final thoughts
As one of my favorite Symfony components, Serializer is both fast and versatile, yet easy to use. If you’re building an API, transforming data between formats, or just want cleaner code — you’ll love what it offers.
Don’t skip it. It does too much heavy lifting to be ignored.