You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feature #39399 [Serializer] Allow to provide (de)normalization context in mapping (ogizanagi)
This PR was squashed before being merged into the 5.3-dev branch.
Discussion
----------
[Serializer] Allow to provide (de)normalization context in mapping
| Q | A
| ------------- | ---
| Branch? | 5.x
| Bug fix? | no
| New feature? | yes <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets | Fix#39039 <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead -->
| License | MIT
| Doc PR | TODO <!-- required for new features -->
As explained in the linked feature request, this brings the ability to configure context on a per-property basis, using Serializer mapping.
Considering:
```php
use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
class Foo
{
/**
* @Serializer\Context({ DateTimeNormalizer::FORMAT_KEY = 'Y-m-d' })
*/
public \DateTime $date;
public \DateTime $anotherDate;
}
```
`$date` will be formatted with a specific format, while `$anotherDate` will use the default configured one (or the one provided in the context while calling `->serialize()` / `->normalize()`).
It can also differentiate normalization and denormalization contexts:
```php
use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
class Foo
{
/**
* @Serializer\Context(
* normalizationContext = { DateTimeNormalizer::FORMAT_KEY = 'Y-m-d' },
* denormalizationContext = { DateTimeNormalizer::FORMAT_KEY = \DateTime::COOKIE },
* )
*/
public \DateTime $date;
}
```
As well as act differently depending on groups:
```php
use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
class Foo
{
/**
* @Serializer\Groups({ "extended" })
* @Serializer\Context({ DateTimeNormalizer::FORMAT_KEY = \DateTime::RFC3339 })
* @Serializer\Context(
* context = { DateTimeNormalizer::FORMAT_KEY = \DateTime::RFC3339_EXTENDED },
* groups = {"extended"},
* )
*/
public \DateTime $date;
}
```
The annotation can be repeated as much as you want to handle the different cases.
Context without groups is always applied first, then context for groups are merged in the provided order.
Context provided when calling `->serialize()` / `->normalize()` acts as the defaults for the properties without context provided in the metadata.
XML mapping (see tests) is a lot verbose due to the required structure to handle groups.
Such metadata contexts are also forwarded to name converters, max depth handlers, callbacks, ...
Of course, PHP 8 attributes are also supported:
```php
use Symfony\Component\Serializer\Annotation as Serializer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
class Foo
{
#[Serializer\Groups(["extended"])]
#[Serializer\Context([DateTimeNormalizer::FORMAT_KEY => \DateTime::RFC3339])]
#[Serializer\Context(
context: [DateTimeNormalizer::FORMAT_KEY => \DateTime::RFC3339_EXTENDED],
groups: ["extended"],
)]
public \DateTime $date;
}
```
The PR should be ready for first batch of reviews / discussions.
- [x] Make Fabbot happy in 5.2
- [x] Missing `@Context` unit tests
- [x] rework xml & phpize values
- [x] Fix lowest build issue with annotations => bumped doctrine annotations to 1.7, as for other components
Commits
-------
7229fa1 [Serializer] Allow to provide (de)normalization context in mapping
thrownewInvalidArgumentException(sprintf('Option "%s" of annotation "%s" must be an array.', $key, static::class));
53
+
}
54
+
}
55
+
56
+
if (!$context && !$normalizationContext && !$denormalizationContext) {
57
+
thrownewInvalidArgumentException(sprintf('At least one of the "context", "normalizationContext", or "denormalizationContext" options of annotation "%s" must be provided as a non-empty array.', static::class));
thrownewInvalidArgumentException(sprintf('Parameter "groups" of annotation "%s" must be a string or an array of strings. Got "%s".', static::class, get_debug_type($group)));
thrownewMappingException(sprintf('Context on "%s::%s()" cannot be added. Context can only be added on methods beginning with "get", "is", "has" or "set".', $className, $method->name));
0 commit comments