New in Symfony 6.4: Serializer Improvements


Class-based Group Attributes

Contributed by Adrian Brajkovic
in #49594.

Serialization groups allow to serialize different sets of attributes from your
entities according to your needs. A group name is an arbitrary string that associates
a property to one or more of those serialization sets.
In Symfony 6.4 we're improving serialization groups so you can also define them
at class level. This will associate all properties to that group, in addition
to the groups that each property optionally associates to:

#[ORM\Entity]
#[Groups(['show_product'])]
class Product
{
// ...

#[ORM\Column(type: 'string', length: 255)]
#[Groups(['list_product'])]
private string $name;

#[ORM\Column(type: 'text')]
private string $description;
}

In this example, the name property belongs to show_product and list_product
groups, but the description property only belongs to the show_product group.

Translatable Objects Normalizer

Contributed by Hubert Lenoir
in #50212.

In Symfony 5.2 we introduced translatable objects, which are objects that
contain all the information needed to translate its own contents, such as the
translation parameters and the translation domain.
In Symfony 6.4, we're introducing a TranslatableObject normalizer, which
translates the contents of these objects to the locale defined in the NORMALIZATION_LOCALE_KEY
option when serializing objects. There's nothing to do to use this new normalizer.
Upgrade your application to Symfony 6.4 or higher and this will work out-of-the-box.

Validation Groups Provider Outside DTOs

Contributed by Yonel Ceruto
in #51348.

Currently, you can determine the sequence of groups to apply dynamically based
on the state of your DTO by implementing the GroupSequenceProviderInterface
in your DTO class:

use Symfony\Component\Validator\GroupSequenceProviderInterface;

#[Assert\GroupSequenceProvider]
class UserDto implements GroupSequenceProviderInterface
{
// ...

public function getGroupSequence(): array|GroupSequence
{
if ($this->isCompanyType()) {
return ['User', 'Company'];
}

return ['User'];
}
}

However, in more advanced cases you might need to use a service to define that
group sequence. A possible solution would be to inject the service in the DTO
constructor, but that's usually out of the scope of the DTO responsibility (and,
strictly speaking, could not fit the SOLID principles).
In Symfony 6.4 we're improving this by allowing you to create a class that
implements the GroupProviderInterface and then use it in your DTO via the
GroupSequenceProvider attribute:

use Symfony\Component\Validator\Constraints as Assert;

#[Assert\GroupSequenceProvider(provider: UserGroupProvider::class)]
class UserDto
{
// ...
}

use Symfony\Component\Validator\Constraints\GroupSequence;
use Symfony\Component\Validator\GroupProviderInterface;

class UserGroupProvider implements GroupProviderInterface
{
public __constructor(private readonly ConfigService $config)
{
}

public function getGroups(object $object): array|GroupSequence
{
if ($this->config->isEnabled()) {
return ['User', $this->config->getGroup()];
}

return ['User'];
}
}

Detailed JSON Decoding Errors

Contributed by Gabriel Ostrolucký
in #51215
and #51172.

Consider the following JSON snippet which contains a certain syntax error:

$jsonContent = "{'foo': 'bar'}";

In current Symfony versions, when trying to deserialize that content, you'll see
this error:

{
"title": "Deserialization Failed",
"detail": "Syntax error"
}

Not very useful, right? In Symfony 6.4 we're improving this significantly.
First, install the seld/jsonlint dependency in your project. Then, upgrade
to Symfony 6.4 or higher and, when the application runs in the debug mode,
you'll see detailed errors like the following:

{
"title": "Deserialization Failed",
"detail": "Parse error on line 1: {'foo': 'bar'} Invalid string, it appears you used single quotes instead of double quotes"
}

Sponsor the Symfony project.