diff --git a/UPGRADE-6.2.md b/UPGRADE-6.2.md index c803677a28272..75fb5db3aee05 100644 --- a/UPGRADE-6.2.md +++ b/UPGRADE-6.2.md @@ -108,6 +108,11 @@ Translation * Deprecate `PhpExtractor` in favor of `PhpAstExtractor` * Add `PhpAstExtractor` (requires [nikic/php-parser](https://github.com/nikic/php-parser) to be installed) +Serializer +---------- + + * Add argument `$groups` to `AttributeMetadata::setSerializedName()` and `AttributeMetadata::getSerializedName()` + Validator --------- diff --git a/src/Symfony/Component/Serializer/Annotation/SerializedName.php b/src/Symfony/Component/Serializer/Annotation/SerializedName.php index b6c6027e8568e..e87adeddd549a 100644 --- a/src/Symfony/Component/Serializer/Annotation/SerializedName.php +++ b/src/Symfony/Component/Serializer/Annotation/SerializedName.php @@ -22,13 +22,22 @@ * * @author Fabien Bourigault */ -#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] +#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY | \Attribute::IS_REPEATABLE)] final class SerializedName { - public function __construct(private string $serializedName) + /** + * @var string[] + */ + private array $groups; + + /** + * @param string|string[] $groups + */ + public function __construct(private string $serializedName, string|array $groups = []) { + $this->groups = (array) $groups; if ('' === $serializedName) { - throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be a non-empty string.', self::class)); + throw new InvalidArgumentException(sprintf('Parameter of annotation "%s" must be a non-empty string.', static::class)); } } @@ -36,4 +45,12 @@ public function getSerializedName(): string { return $this->serializedName; } + + /** + * @return string[] + */ + public function getGroups(): array + { + return $this->groups; + } } diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 3342ada2fea86..9478572c5c3b8 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -12,6 +12,8 @@ CHANGELOG * Change the signature of `ClassMetadataInterface::setClassDiscriminatorMapping()` to `setClassDiscriminatorMapping(?ClassDiscriminatorMapping)` * Add option YamlEncoder::YAML_INDENTATION to YamlEncoder constructor options to configure additional indentation for each level of nesting. This allows configuring indentation in the service configuration. * Add `SerializedPath` annotation to flatten nested attributes + * Add serialized name group support + * Add argument `$groups` to `AttributeMetadata::setSerializedName()` and `AttributeMetadata::getSerializedName()` 6.1 --- diff --git a/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php b/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php index 22cc711a7e2c8..9cc1ca3aca311 100644 --- a/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php +++ b/src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php @@ -42,13 +42,13 @@ class AttributeMetadata implements AttributeMetadataInterface public $maxDepth; /** - * @var string|null + * @var array An array of serialized names by group * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use - * {@link getSerializedName()} instead. + * {@link getSerializedNames()} instead. */ - public $serializedName; + public $serializedName = []; /** * @internal This property is public in order to reduce the size of the @@ -116,20 +116,68 @@ public function getMaxDepth(): ?int return $this->maxDepth; } - public function setSerializedName(string $serializedName = null) + public function setSerializedNames(array $serializedNames): void + { + $this->serializedName = $serializedNames; + } + + /** + * Set a serialization name for given groups. + * + * @param string[] $groups + */ + public function setSerializedName(string $serializedName = null/* , array $groups = [] */) { if (1 > \func_num_args()) { trigger_deprecation('symfony/serializer', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); } + + if (\func_num_args() < 2) { + $groups = []; + } else { + $groups = func_get_arg(1); + + if (!\is_array($groups)) { + throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be array, "%s" given.', __METHOD__, get_debug_type($groups))); + } + } - $this->serializedName = $serializedName; + foreach ($groups ?: ['*'] as $group) { + $this->serializedName[$group] = $serializedName; + } } - public function getSerializedName(): ?string + public function getSerializedNames(): array { return $this->serializedName; } + /** + * Gets the serialization name for given groups. + * + * @param string[] $groups + */ + public function getSerializedName(/* array $groups = [] */): ?string + { + if (\func_num_args() < 1) { + $groups = []; + } else { + $groups = func_get_arg(0); + + if (!\is_array($groups)) { + throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be array, "%s" given.', __METHOD__, get_debug_type($groups))); + } + } + + foreach ($groups as $group) { + if (isset($this->serializedName[$group])) { + return $this->serializedName[$group]; + } + } + + return $this->serializedName['*'] ?? null; + } + public function setSerializedPath(PropertyPath $serializedPath = null): void { $this->serializedPath = $serializedPath; @@ -210,7 +258,7 @@ public function merge(AttributeMetadataInterface $attributeMetadata) // Overwrite only if not defined $this->maxDepth ??= $attributeMetadata->getMaxDepth(); - $this->serializedName ??= $attributeMetadata->getSerializedName(); + $this->serializedName ??= $attributeMetadata->getSerializedNames(); $this->serializedPath ??= $attributeMetadata->getSerializedPath(); // Overwrite only if both contexts are empty @@ -233,4 +281,16 @@ public function __sleep(): array { return ['name', 'groups', 'maxDepth', 'serializedName', 'serializedPath', 'ignore', 'normalizationContexts', 'denormalizationContexts']; } + + public function __wakeup() + { + // Preserve compatibility with existing serialized payloads + if (null === $this->serializedName) { + $this->serializedName = []; + } elseif (\is_string($this->serializedName)) { + $this->serializedName = [ + '*' => $this->serializedName, + ]; + } + } } diff --git a/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php b/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php index 67ca8d3c0631c..70d38db2bf3e0 100644 --- a/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php +++ b/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php @@ -52,14 +52,32 @@ public function setMaxDepth(?int $maxDepth); public function getMaxDepth(): ?int; /** - * Sets the serialization name for this attribute. + * Sets the serialization names for given groups. + * + * @param array $serializedNames + */ + public function setSerializedNames(array $serializedNames): void; + + /** + * Set a serialization name for given groups. + * + * @param string[] $groups */ - public function setSerializedName(?string $serializedName); + public function setSerializedName(?string $serializedName/* , array $groups = [] */); /** - * Gets the serialization name for this attribute. + * Gets the serialization name for given groups. + * + * @param string[] $groups + */ + public function getSerializedName(/* array $groups = [] */): ?string; + + /** + * Gets all the serialization names per group ("*" being the default serialization name). + * + * @return array */ - public function getSerializedName(): ?string; + public function getSerializedNames(): array; public function setSerializedPath(?PropertyPath $serializedPath): void; diff --git a/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactoryCompiler.php b/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactoryCompiler.php index f01fe9ce2f085..ea82f68ca9529 100644 --- a/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactoryCompiler.php +++ b/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactoryCompiler.php @@ -47,7 +47,7 @@ private function generateDeclaredClassMetadata(array $classMetadatas): string $attributesMetadata[$attributeMetadata->getName()] = [ $attributeMetadata->getGroups(), $attributeMetadata->getMaxDepth(), - $attributeMetadata->getSerializedName(), + $attributeMetadata->getSerializedNames(), $attributeMetadata->getSerializedPath(), ]; } diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/AnnotationLoader.php b/src/Symfony/Component/Serializer/Mapping/Loader/AnnotationLoader.php index cfcee8bd5013d..052bd9cac14de 100644 --- a/src/Symfony/Component/Serializer/Mapping/Loader/AnnotationLoader.php +++ b/src/Symfony/Component/Serializer/Mapping/Loader/AnnotationLoader.php @@ -82,7 +82,7 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata): bool } elseif ($annotation instanceof MaxDepth) { $attributesMetadata[$property->name]->setMaxDepth($annotation->getMaxDepth()); } elseif ($annotation instanceof SerializedName) { - $attributesMetadata[$property->name]->setSerializedName($annotation->getSerializedName()); + $attributesMetadata[$property->name]->setSerializedName($annotation->getSerializedName(), $annotation->getGroups()); } elseif ($annotation instanceof SerializedPath) { $attributesMetadata[$property->name]->setSerializedPath($annotation->getSerializedPath()); } elseif ($annotation instanceof Ignore) { @@ -137,7 +137,7 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata): bool throw new MappingException(sprintf('SerializedName on "%s::%s()" cannot be added. SerializedName can only be added on methods beginning with "get", "is", "has" or "set".', $className, $method->name)); } - $attributeMetadata->setSerializedName($annotation->getSerializedName()); + $attributeMetadata->setSerializedName($annotation->getSerializedName(), $annotation->getGroups()); } elseif ($annotation instanceof SerializedPath) { if (!$accessorOrMutator) { throw new MappingException(sprintf('SerializedPath on "%s::%s()" cannot be added. SerializedPath can only be added on methods beginning with "get", "is", "has" or "set".', $className, $method->name)); diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php b/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php index 3dc3b96c69c94..c0f00936752aa 100644 --- a/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php @@ -67,7 +67,13 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata): bool } if (isset($attribute['serialized-name'])) { - $attributeMetadata->setSerializedName((string) $attribute['serialized-name']); + $attributeMetadata->setSerializedName((string) $attribute['serialized-name'], []); + } + + foreach ($attribute->serialized_name as $node) { + $serializedName = (string) $node['name']; + $groups = (array) $node->group; + $attributeMetadata->setSerializedName('' === $serializedName ? null : $serializedName, $groups); } if (isset($attribute['serialized-path'])) { diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php index 0fdfcc511093a..993cf6542e8ca 100644 --- a/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php @@ -86,11 +86,24 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata): bool } if (isset($data['serialized_name'])) { - if (!\is_string($data['serialized_name']) || '' === $data['serialized_name']) { - throw new MappingException(sprintf('The "serialized_name" value must be a non-empty string in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName())); - } + $serializedNames = $data['serialized_name']; - $attributeMetadata->setSerializedName($data['serialized_name']); + if (\is_string($serializedNames)) { + if ('' === $serializedNames) { + throw new MappingException(sprintf('The "serialized_name" value must be a non-empty string in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName())); + } + $attributeMetadata->setSerializedName($serializedNames, []); + } elseif (\is_array($serializedNames)) { + foreach ($serializedNames as $serializedName => $groups) { + if (!\is_string($serializedName) || !$serializedName) { + throw new MappingException(sprintf('The key for "serialized_name" array must be a non-empty string in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName())); + } + + $attributeMetadata->setSerializedName($serializedName, (array) $groups); + } + } else { + throw new MappingException(sprintf('The "serialized_name" value must be a non-empty string or an array of serialized name/groups in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName())); + } } if (isset($data['serialized_path'])) { diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd b/src/Symfony/Component/Serializer/Mapping/Loader/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd index f5f6cca9f0f54..50a3019d0b60d 100644 --- a/src/Symfony/Component/Serializer/Mapping/Loader/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd +++ b/src/Symfony/Component/Serializer/Mapping/Loader/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd @@ -54,6 +54,19 @@ + + + + + + + + + + + + + + diff --git a/src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php b/src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php index 920e81869561e..93fb159b52e8f 100644 --- a/src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php +++ b/src/Symfony/Component/Serializer/NameConverter/MetadataAwareNameConverter.php @@ -46,7 +46,7 @@ public function normalize(string $propertyName, string $class = null, string $fo } if (!\array_key_exists($class, self::$normalizeCache) || !\array_key_exists($propertyName, self::$normalizeCache[$class])) { - self::$normalizeCache[$class][$propertyName] = $this->getCacheValueForNormalization($propertyName, $class); + self::$normalizeCache[$class][$propertyName] = $this->getCacheValueForNormalization($propertyName, $class, $context); } return self::$normalizeCache[$class][$propertyName] ?? $this->normalizeFallback($propertyName, $class, $format, $context); @@ -66,7 +66,7 @@ public function denormalize(string $propertyName, string $class = null, string $ return self::$denormalizeCache[$cacheKey][$propertyName] ?? $this->denormalizeFallback($propertyName, $class, $format, $context); } - private function getCacheValueForNormalization(string $propertyName, string $class): ?string + private function getCacheValueForNormalization(string $propertyName, string $class, array $context): ?string { if (!$this->metadataFactory->hasMetadataFor($class)) { return null; @@ -77,11 +77,14 @@ private function getCacheValueForNormalization(string $propertyName, string $cla return null; } - if (null !== $attributesMetadata[$propertyName]->getSerializedName() && null !== $attributesMetadata[$propertyName]->getSerializedPath()) { + $groups = (array) ($context[AbstractNormalizer::GROUPS] ?? []); + + $serializedName = $attributesMetadata[$propertyName]->getSerializedName($groups); + if (null !== $serializedName && null !== $attributesMetadata[$propertyName]->getSerializedPath()) { throw new LogicException(sprintf('Found SerializedName and SerializedPath annotations on property "%s" of class "%s".', $propertyName, $class)); } - return $attributesMetadata[$propertyName]->getSerializedName() ?? null; + return $serializedName ?? null; } private function normalizeFallback(string $propertyName, string $class = null, string $format = null, array $context = []): string @@ -114,23 +117,24 @@ private function getCacheValueForAttributesMetadata(string $class, array $contex $cache = []; foreach ($classMetadata->getAttributesMetadata() as $name => $metadata) { - if (null === $metadata->getSerializedName()) { + $contextGroups = (array) ($context[AbstractNormalizer::GROUPS] ?? []); + if (null === $serializedName = $metadata->getSerializedName($contextGroups)) { continue; } - if (null !== $metadata->getSerializedName() && null !== $metadata->getSerializedPath()) { + if (null !== $metadata->getSerializedPath()) { throw new LogicException(sprintf('Found SerializedName and SerializedPath annotations on property "%s" of class "%s".', $name, $class)); } $groups = $metadata->getGroups(); - if (!$groups && ($context[AbstractNormalizer::GROUPS] ?? [])) { + if (!$groups && $contextGroups) { continue; } - if ($groups && !array_intersect($groups, (array) ($context[AbstractNormalizer::GROUPS] ?? []))) { + if ($groups && !array_intersect($groups, $contextGroups)) { continue; } - $cache[$metadata->getSerializedName()] = $name; + $cache[$serializedName] = $name; } return $cache; diff --git a/src/Symfony/Component/Serializer/Tests/Annotation/SerializedNameTest.php b/src/Symfony/Component/Serializer/Tests/Annotation/SerializedNameTest.php index f4dd82d7fad9b..a1744fd1308a6 100644 --- a/src/Symfony/Component/Serializer/Tests/Annotation/SerializedNameTest.php +++ b/src/Symfony/Component/Serializer/Tests/Annotation/SerializedNameTest.php @@ -31,6 +31,21 @@ public function testNotAStringSerializedNameParameter() public function testSerializedNameParameters() { $maxDepth = new SerializedName('foo'); - $this->assertEquals('foo', $maxDepth->getSerializedName()); + $this->assertSame('foo', $maxDepth->getSerializedName()); + $this->assertSame([], $maxDepth->getGroups()); + } + + public function testSerializedNameParametersWithArrayGroups() + { + $maxDepth = new SerializedName('foo', ['bar', 'baz']); + $this->assertSame('foo', $maxDepth->getSerializedName()); + $this->assertSame(['bar', 'baz'], $maxDepth->getGroups()); + } + + public function testSerializedNameParametersWithStringGroup() + { + $maxDepth = new SerializedName('foo', 'bar'); + $this->assertSame('foo', $maxDepth->getSerializedName()); + $this->assertSame(['bar'], $maxDepth->getGroups()); } } diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/Annotations/SerializedNameDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/Annotations/SerializedNameDummy.php index 1eaa579b466fa..7fbc840f3f84a 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/Annotations/SerializedNameDummy.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/Annotations/SerializedNameDummy.php @@ -32,6 +32,13 @@ class SerializedNameDummy */ public $child; + /** + * @SerializedName("nameOne") + * @SerializedName("nameTwo", groups={"a", "b"}) + * @SerializedName("nameThree", groups="c") + */ + public $corge; + /** * @SerializedName("qux") */ diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/SerializedNameDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/SerializedNameDummy.php index fe0a67e83cf67..c728bd52d59ef 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/SerializedNameDummy.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/SerializedNameDummy.php @@ -30,6 +30,11 @@ class SerializedNameDummy */ public $child; + #[SerializedName('nameOne')] + #[SerializedName('nameTwo', ['a', 'b'])] + #[SerializedName('nameThree', ['c'])] + public $corge; + #[SerializedName('qux')] public function getBar() { diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.xml b/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.xml index 4890f56bfd0f9..52396bd55aeb2 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.xml +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.xml @@ -23,6 +23,15 @@ + + + groupA + groupB + + + groupC + + diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.yml b/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.yml index 7519b979efa96..c57fa87059c25 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.yml +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/serialization.yml @@ -16,6 +16,10 @@ serialized_name: 'baz' bar: serialized_name: 'qux' + quux: + serialized_name: + nameOne: ['groupA', 'groupB'] + nameTwo: 'groupC' 'Symfony\Component\Serializer\Tests\Fixtures\Annotations\SerializedPathDummy': attributes: three: diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/serializer.class.metadata.php b/src/Symfony/Component/Serializer/Tests/Fixtures/serializer.class.metadata.php index 4773d22675091..d05977f69c47c 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/serializer.class.metadata.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/serializer.class.metadata.php @@ -5,10 +5,10 @@ return [ 'Symfony\Component\Serializer\Tests\Fixtures\Dummy' => [ [ - 'foo' => [[], null, null], - 'bar' => [[], null, null], - 'baz' => [[], null, null], - 'qux' => [[], null, null], + 'foo' => [[], null, []], + 'bar' => [[], null, []], + 'baz' => [[], null, []], + 'qux' => [[], null, []], ], null, ], diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/AttributeMetadataTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/AttributeMetadataTest.php index 1f1b291beb7f0..02dd0e7dde428 100644 --- a/src/Symfony/Component/Serializer/Tests/Mapping/AttributeMetadataTest.php +++ b/src/Symfony/Component/Serializer/Tests/Mapping/AttributeMetadataTest.php @@ -51,12 +51,64 @@ public function testMaxDepth() $this->assertEquals(69, $attributeMetadata->getMaxDepth()); } - public function testSerializedName() + public function testSerializedNames() { $attributeMetadata = new AttributeMetadata('name'); - $attributeMetadata->setSerializedName('serialized_name'); - $this->assertEquals('serialized_name', $attributeMetadata->getSerializedName()); + $this->assertSame([], $attributeMetadata->getSerializedNames()); + + $attributeMetadata->setSerializedNames([ + 'foo-group' => 'foo', + 'bar-group' => 'bar', + ]); + + $this->assertEquals([ + 'foo-group' => 'foo', + 'bar-group' => 'bar', + ], $attributeMetadata->getSerializedNames()); + + $attributeMetadata->setSerializedName('baz', ['baz-group']); + $this->assertEquals([ + 'foo-group' => 'foo', + 'bar-group' => 'bar', + 'baz-group' => 'baz', + ], $attributeMetadata->getSerializedNames()); + + $attributeMetadata->setSerializedName('bar', ['baz-group']); + $this->assertEquals([ + 'foo-group' => 'foo', + 'bar-group' => 'bar', + 'baz-group' => 'bar', + ], $attributeMetadata->getSerializedNames()); + + $this->assertNull($attributeMetadata->getSerializedName(['unknown'])); + $this->assertSame('bar', $attributeMetadata->getSerializedName(['bar-group'])); + $this->assertSame('foo', $attributeMetadata->getSerializedName(['foo-group', 'bar-group'])); + $this->assertSame('bar', $attributeMetadata->getSerializedName(['bar-group', 'foo-group'])); + } + + public function testSerializedNamesWithoutSpecificGroup() + { + $attributeMetadata = new AttributeMetadata('name'); + + $attributeMetadata->setSerializedName('foo', []); + $this->assertSame('foo', $attributeMetadata->getSerializedName([])); + $this->assertSame('foo', $attributeMetadata->getSerializedName(['bar'])); + + $this->assertSame([ + '*' => 'foo', + ], $attributeMetadata->getSerializedNames()); + } + + public function testNullSerializedNames() + { + $attributeMetadata = new AttributeMetadata('name'); + + $attributeMetadata->setSerializedName(null, []); + + $this->assertSame([ + '*' => null, + ], $attributeMetadata->getSerializedNames()); } public function testSerializedPath() @@ -133,6 +185,10 @@ public function testMerge() $attributeMetadata1 = new AttributeMetadata('a1'); $attributeMetadata1->addGroup('a'); $attributeMetadata1->addGroup('b'); + $attributeMetadata1->setSerializedNames([ + 'group-a' => 'name-a', + 'group-b' => 'name-b', + ]); $attributeMetadata2 = new AttributeMetadata('a2'); $attributeMetadata2->addGroup('a'); @@ -149,7 +205,10 @@ public function testMerge() $this->assertEquals(['a', 'b', 'c'], $attributeMetadata1->getGroups()); $this->assertEquals(2, $attributeMetadata1->getMaxDepth()); - $this->assertEquals('a3', $attributeMetadata1->getSerializedName()); + $this->assertEquals([ + 'group-a' => 'name-a', + 'group-b' => 'name-b', + ], $attributeMetadata1->getSerializedNames()); $this->assertEquals($serializedPath, $attributeMetadata1->getSerializedPath()); $this->assertSame(['a' => ['foo' => 'bar']], $attributeMetadata1->getNormalizationContexts()); $this->assertSame(['c' => ['baz' => 'qux']], $attributeMetadata1->getDenormalizationContexts()); @@ -157,6 +216,27 @@ public function testMerge() } public function testContextsNotMergedIfAlreadyDefined() + { + $attributeMetadata1 = new AttributeMetadata('a1'); + $attributeMetadata1->setSerializedNames([ + 'group-a' => 'name-a', + 'group-b' => 'name-b', + ]); + + $attributeMetadata2 = new AttributeMetadata('a2'); + $attributeMetadata2->setSerializedNames([ + 'group-b' => 'name-c', + ]); + + $attributeMetadata1->merge($attributeMetadata2); + + self::assertSame([ + 'group-a' => 'name-a', + 'group-b' => 'name-b', + ], $attributeMetadata1->getSerializedNames()); + } + + public function testSerializedNamesNotMergedIfAlreadyDefined() { $attributeMetadata1 = new AttributeMetadata('a1'); $attributeMetadata1->setNormalizationContextForGroups(['foo' => 'not overridden'], ['a']); @@ -178,11 +258,39 @@ public function testSerialize() $attributeMetadata->addGroup('a'); $attributeMetadata->addGroup('b'); $attributeMetadata->setMaxDepth(3); - $attributeMetadata->setSerializedName('serialized_name'); + $attributeMetadata->setSerializedNames([ + 'group-a' => 'name-a', + ]); $serializedPath = new PropertyPath('[serialized][path]'); $attributeMetadata->setSerializedPath($serializedPath); $serialized = serialize($attributeMetadata); $this->assertEquals($attributeMetadata, unserialize($serialized)); } + + public function testSerializeSerializedNameNullCompatibility() + { + $attributeMetadata = new AttributeMetadata('attribute'); + $attributeMetadata->serializedName = null; + + $serialized = serialize($attributeMetadata); + $unserialized = unserialize($serialized); + + $this->assertSame([], $unserialized->serializedName); + $this->assertNull($unserialized->getSerializedName()); + } + + public function testSerializeSerializedNameStringCompatibility() + { + $attributeMetadata = new AttributeMetadata('attribute'); + $attributeMetadata->serializedName = 'foo'; + + $serialized = serialize($attributeMetadata); + $unserialized = unserialize($serialized); + + $this->assertSame([ + '*' => 'foo', + ], $unserialized->serializedName); + $this->assertSame('foo', $unserialized->getSerializedName()); + } } diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryCompilerTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryCompilerTest.php index 5ce1931ba0cab..d0abaa2bec06c 100644 --- a/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryCompilerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryCompilerTest.php @@ -62,10 +62,10 @@ public function testItDumpMetadata() $this->assertArrayHasKey(Dummy::class, $compiledMetadata); $this->assertEquals([ [ - 'foo' => [[], null, null, null], - 'bar' => [[], null, null, null], - 'baz' => [[], null, null, null], - 'qux' => [[], null, null, null], + 'foo' => [[], null, [], null], + 'bar' => [[], null, [], null], + 'baz' => [[], null, [], null], + 'qux' => [[], null, [], null], ], null, ], $compiledMetadata[Dummy::class]); @@ -73,9 +73,9 @@ public function testItDumpMetadata() $this->assertArrayHasKey(MaxDepthDummy::class, $compiledMetadata); $this->assertEquals([ [ - 'foo' => [[], 2, null, null], - 'bar' => [[], 3, null, null], - 'child' => [[], null, null, null], + 'foo' => [[], 2, [], null], + 'bar' => [[], 3, [], null], + 'child' => [[], null, [], null], ], null, ], $compiledMetadata[MaxDepthDummy::class]); @@ -83,10 +83,16 @@ public function testItDumpMetadata() $this->assertArrayHasKey(SerializedNameDummy::class, $compiledMetadata); $this->assertEquals([ [ - 'foo' => [[], null, 'baz', null], - 'bar' => [[], null, 'qux', null], - 'quux' => [[], null, null, null], - 'child' => [[], null, null, null], + 'foo' => [[], null, ['*' => 'baz'], null], + 'bar' => [[], null, ['*' => 'qux'], null], + 'quux' => [[], null, [], null], + 'child' => [[], null, [], null], + 'corge' => [[], null, [ + 'a' => 'nameTwo', + 'b' => 'nameTwo', + 'c' => 'nameThree', + '*' => 'nameOne', + ], null], ], null, ], $compiledMetadata[SerializedNameDummy::class]); @@ -94,8 +100,8 @@ public function testItDumpMetadata() $this->assertArrayHasKey(SerializedPathDummy::class, $compiledMetadata); $this->assertEquals([ [ - 'three' => [[], null, null, '[one][two]'], - 'seven' => [[], null, null, '[three][four]'], + 'three' => [[], null, [], '[one][two]'], + 'seven' => [[], null, [], '[three][four]'], ], null, ], $compiledMetadata[SerializedPathDummy::class]); diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/Loader/AnnotationLoaderTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/Loader/AnnotationLoaderTest.php index 0747ca3f54c7a..0d8cd5ea9269c 100644 --- a/src/Symfony/Component/Serializer/Tests/Mapping/Loader/AnnotationLoaderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Mapping/Loader/AnnotationLoaderTest.php @@ -89,8 +89,15 @@ public function testLoadSerializedName() $this->loader->loadClassMetadata($classMetadata); $attributesMetadata = $classMetadata->getAttributesMetadata(); + $this->assertEquals('baz', $attributesMetadata['foo']->getSerializedName()); $this->assertEquals('qux', $attributesMetadata['bar']->getSerializedName()); + $this->assertEquals([ + 'a' => 'nameTwo', + 'b' => 'nameTwo', + 'c' => 'nameThree', + '*' => 'nameOne', + ], $attributesMetadata['corge']->getSerializedNames()); } public function testLoadSerializedPath() diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/Loader/XmlFileLoaderTest.php index b1e9ed7222636..a24463d319594 100644 --- a/src/Symfony/Component/Serializer/Tests/Mapping/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Mapping/Loader/XmlFileLoaderTest.php @@ -82,6 +82,10 @@ public function testSerializedName() $attributesMetadata = $classMetadata->getAttributesMetadata(); $this->assertEquals('baz', $attributesMetadata['foo']->getSerializedName()); $this->assertEquals('qux', $attributesMetadata['bar']->getSerializedName()); + + $this->assertEquals('nameDefault', $attributesMetadata['quux']->getSerializedName()); + $this->assertEquals('nameOne', $attributesMetadata['quux']->getSerializedName(['groupB'])); + $this->assertEquals('nameTwo', $attributesMetadata['quux']->getSerializedName(['groupC'])); } public function testSerializedPath() diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/Loader/YamlFileLoaderTest.php index bbe0a99aeab89..27b854b684cae 100644 --- a/src/Symfony/Component/Serializer/Tests/Mapping/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Mapping/Loader/YamlFileLoaderTest.php @@ -96,6 +96,10 @@ public function testSerializedName() $attributesMetadata = $classMetadata->getAttributesMetadata(); $this->assertEquals('baz', $attributesMetadata['foo']->getSerializedName()); $this->assertEquals('qux', $attributesMetadata['bar']->getSerializedName()); + + $this->assertEquals('nameOne', $attributesMetadata['quux']->getSerializedName(['groupA'])); + $this->assertEquals('nameOne', $attributesMetadata['quux']->getSerializedName(['groupB'])); + $this->assertEquals('nameTwo', $attributesMetadata['quux']->getSerializedName(['groupC'])); } public function testSerializedPath() pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy