Skip to content

Commit 7192d29

Browse files
committed
feature #38151 [Serializer] add UidNormalizer (guillbdx, norkunas)
This PR was merged into the 5.2-dev branch. Discussion ---------- [Serializer] add UidNormalizer | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | #36102 | License | MIT | Doc PR | symfony/symfony-docs#... <!-- required for new features --> UUID and ULID normalizer. Continuation of #36406 Commits ------- d6a8993 Update based on feedback 1c21c78 UidNormalizer.
2 parents be6146c + d6a8993 commit 7192d29

File tree

4 files changed

+171
-0
lines changed

4 files changed

+171
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
4545
use Symfony\Component\Serializer\Normalizer\ProblemNormalizer;
4646
use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
47+
use Symfony\Component\Serializer\Normalizer\UidNormalizer;
4748
use Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer;
4849
use Symfony\Component\Serializer\Serializer;
4950
use Symfony\Component\Serializer\SerializerInterface;
@@ -106,6 +107,9 @@
106107
->args([service('serializer.property_accessor')])
107108
->tag('serializer.normalizer', ['priority' => 1000])
108109

110+
->set('serializer.normalizer.uid', UidNormalizer::class)
111+
->tag('serializer.normalizer', ['priority' => -915])
112+
109113
->set('serializer.normalizer.object', ObjectNormalizer::class)
110114
->args([
111115
service('serializer.mapping.class_metadata_factory'),

src/Symfony/Component/Serializer/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
-----
66

77
* added `CompiledClassMetadataFactory` and `ClassMetadataFactoryCompiler` for faster metadata loading.
8+
* added `UidNormalizer`
89

910
5.1.0
1011
-----
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Serializer\Normalizer;
13+
14+
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
15+
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
16+
use Symfony\Component\Uid\AbstractUid;
17+
use Symfony\Component\Uid\Ulid;
18+
use Symfony\Component\Uid\Uuid;
19+
20+
final class UidNormalizer implements NormalizerInterface, DenormalizerInterface, CacheableSupportsMethodInterface
21+
{
22+
/**
23+
* {@inheritdoc}
24+
*/
25+
public function normalize($object, string $format = null, array $context = [])
26+
{
27+
if (!$object instanceof AbstractUid) {
28+
throw new InvalidArgumentException('The object must be an instance of "Symfony\Component\Uid\AbstractUid".');
29+
}
30+
31+
return (string) $object;
32+
}
33+
34+
/**
35+
* {@inheritdoc}
36+
*/
37+
public function supportsNormalization($data, string $format = null)
38+
{
39+
return $data instanceof AbstractUid;
40+
}
41+
42+
/**
43+
* {@inheritdoc}
44+
*/
45+
public function denormalize($data, string $type, string $format = null, array $context = [])
46+
{
47+
try {
48+
$uid = Ulid::class === $type ? Ulid::fromString($data) : Uuid::fromString($data);
49+
} catch (\InvalidArgumentException $exception) {
50+
throw new NotNormalizableValueException(sprintf('The data is not a valid "%s" string representation.', $type));
51+
}
52+
53+
return $uid;
54+
}
55+
56+
/**
57+
* {@inheritdoc}
58+
*/
59+
public function supportsDenormalization($data, string $type, string $format = null)
60+
{
61+
return is_a($type, AbstractUid::class, true);
62+
}
63+
64+
/**
65+
* {@inheritdoc}
66+
*/
67+
public function hasCacheableSupportsMethod(): bool
68+
{
69+
return __CLASS__ === static::class;
70+
}
71+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
namespace Symfony\Component\Serializer\Tests\Normalizer;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
7+
use Symfony\Component\Serializer\Normalizer\UidNormalizer;
8+
use Symfony\Component\Uid\AbstractUid;
9+
use Symfony\Component\Uid\Ulid;
10+
use Symfony\Component\Uid\Uuid;
11+
use Symfony\Component\Uid\UuidV1;
12+
use Symfony\Component\Uid\UuidV3;
13+
use Symfony\Component\Uid\UuidV4;
14+
use Symfony\Component\Uid\UuidV5;
15+
use Symfony\Component\Uid\UuidV6;
16+
17+
class UidNormalizerTest extends TestCase
18+
{
19+
/**
20+
* @var UidNormalizer
21+
*/
22+
private $normalizer;
23+
24+
protected function setUp(): void
25+
{
26+
$this->normalizer = new UidNormalizer();
27+
}
28+
29+
public function dataProvider()
30+
{
31+
return [
32+
['9b7541de-6f87-11ea-ab3c-9da9a81562fc', UuidV1::class],
33+
['e576629b-ff34-3642-9c08-1f5219f0d45b', UuidV3::class],
34+
['4126dbc1-488e-4f6e-aadd-775dcbac482e', UuidV4::class],
35+
['18cdf3d3-ea1b-5b23-a9c5-40abd0e2df22', UuidV5::class],
36+
['1ea6ecef-eb9a-66fe-b62b-957b45f17e43', UuidV6::class],
37+
['1ea6ecef-eb9a-66fe-b62b-957b45f17e43', AbstractUid::class],
38+
['01E4BYF64YZ97MDV6RH0HAMN6X', Ulid::class],
39+
];
40+
}
41+
42+
public function testSupportsNormalization()
43+
{
44+
$this->assertTrue($this->normalizer->supportsNormalization(Uuid::v1()));
45+
$this->assertTrue($this->normalizer->supportsNormalization(Uuid::v3(Uuid::v1(), 'foo')));
46+
$this->assertTrue($this->normalizer->supportsNormalization(Uuid::v4()));
47+
$this->assertTrue($this->normalizer->supportsNormalization(Uuid::v5(Uuid::v1(), 'foo')));
48+
$this->assertTrue($this->normalizer->supportsNormalization(Uuid::v6()));
49+
$this->assertTrue($this->normalizer->supportsNormalization(new Ulid()));
50+
$this->assertFalse($this->normalizer->supportsNormalization(new \stdClass()));
51+
}
52+
53+
/**
54+
* @dataProvider dataProvider
55+
*/
56+
public function testNormalize($uuidString, $class)
57+
{
58+
if (Ulid::class === $class) {
59+
$this->assertEquals($uuidString, $this->normalizer->normalize(Ulid::fromString($uuidString)));
60+
} else {
61+
$this->assertEquals($uuidString, $this->normalizer->normalize(Uuid::fromString($uuidString)));
62+
}
63+
}
64+
65+
public function testNormalizeForNonUid()
66+
{
67+
$this->expectException(InvalidArgumentException::class);
68+
$this->normalizer->normalize(new \stdClass());
69+
}
70+
71+
/**
72+
* @dataProvider dataProvider
73+
*/
74+
public function testSupportsDenormalization($uuidString, $class)
75+
{
76+
$this->assertTrue($this->normalizer->supportsDenormalization($uuidString, $class));
77+
}
78+
79+
public function testSupportsDenormalizationForNonUid()
80+
{
81+
$this->assertFalse($this->normalizer->supportsDenormalization('foo', \stdClass::class));
82+
}
83+
84+
/**
85+
* @dataProvider dataProvider
86+
*/
87+
public function testDenormalize($uuidString, $class)
88+
{
89+
if (Ulid::class === $class) {
90+
$this->assertEquals(new Ulid($uuidString), $this->normalizer->denormalize($uuidString, $class));
91+
} else {
92+
$this->assertEquals(Uuid::fromString($uuidString), $this->normalizer->denormalize($uuidString, $class));
93+
}
94+
}
95+
}

0 commit comments

Comments
 (0)