Skip to content

Commit 8526d7c

Browse files
dunglasfabpot
authored andcommitted
[Serializer] Add an @ignore annotation
1 parent eb26992 commit 8526d7c

19 files changed

+218
-8
lines changed

src/Symfony/Component/PropertyInfo/Extractor/SerializerExtractor.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ public function getProperties(string $class, array $context = []): ?array
4747
$serializerClassMetadata = $this->classMetadataFactory->getMetadataFor($class);
4848

4949
foreach ($serializerClassMetadata->getAttributesMetadata() as $serializerAttributeMetadata) {
50-
if (array_intersect($context['serializer_groups'], $serializerAttributeMetadata->getGroups())) {
50+
$ignored = method_exists($serializerClassMetadata, 'isIgnored') && $serializerAttributeMetadata->isIgnored();
51+
if (!$ignored && array_intersect($context['serializer_groups'], $serializerAttributeMetadata->getGroups())) {
5152
$properties[] = $serializerAttributeMetadata->getName();
5253
}
5354
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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\Annotation;
13+
14+
/**
15+
* Annotation class for @Ignore().
16+
*
17+
* @Annotation
18+
* @Target({"PROPERTY", "METHOD"})
19+
*
20+
* @author Kévin Dunglas <dunglas@gmail.com>
21+
*/
22+
final class Ignore
23+
{
24+
}

src/Symfony/Component/Serializer/CHANGELOG.md

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

77
* added support for scalar values denormalization
88
* added support for `\stdClass` to `ObjectNormalizer`
9+
* added the ability to ignore properties using metadata (e.g. `@Symfony\Component\Serializer\Annotation\Ignore`)
910

1011
5.0.0
1112
-----

src/Symfony/Component/Serializer/Mapping/AttributeMetadata.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ class AttributeMetadata implements AttributeMetadataInterface
5050
*/
5151
public $serializedName;
5252

53+
/**
54+
* @var bool
55+
*
56+
* @internal This property is public in order to reduce the size of the
57+
* class' serialized representation. Do not access it. Use
58+
* {@link isIgnored()} instead.
59+
*/
60+
public $ignore = false;
61+
5362
public function __construct(string $name)
5463
{
5564
$this->name = $name;
@@ -113,6 +122,22 @@ public function getSerializedName(): ?string
113122
return $this->serializedName;
114123
}
115124

125+
/**
126+
* {@inheritdoc}
127+
*/
128+
public function setIgnore(bool $ignore)
129+
{
130+
$this->ignore = $ignore;
131+
}
132+
133+
/**
134+
* {@inheritdoc}
135+
*/
136+
public function isIgnored(): bool
137+
{
138+
return $this->ignore;
139+
}
140+
116141
/**
117142
* {@inheritdoc}
118143
*/
@@ -131,6 +156,10 @@ public function merge(AttributeMetadataInterface $attributeMetadata)
131156
if (null === $this->serializedName) {
132157
$this->serializedName = $attributeMetadata->getSerializedName();
133158
}
159+
160+
if ($ignore = $attributeMetadata->isIgnored()) {
161+
$this->ignore = $ignore;
162+
}
134163
}
135164

136165
/**
@@ -140,6 +169,6 @@ public function merge(AttributeMetadataInterface $attributeMetadata)
140169
*/
141170
public function __sleep()
142171
{
143-
return ['name', 'groups', 'maxDepth', 'serializedName'];
172+
return ['name', 'groups', 'maxDepth', 'serializedName', 'ignore'];
144173
}
145174
}

src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ public function setSerializedName(string $serializedName = null);
6161
*/
6262
public function getSerializedName(): ?string;
6363

64+
/**
65+
* Sets if this attribute must be ignored or not.
66+
*/
67+
public function setIgnore(bool $ignore);
68+
69+
/**
70+
* Gets if this attribute is ignored or not.
71+
*/
72+
public function isIgnored(): bool;
73+
6474
/**
6575
* Merges an {@see AttributeMetadataInterface} with in the current one.
6676
*/

src/Symfony/Component/Serializer/Mapping/Loader/AnnotationLoader.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Doctrine\Common\Annotations\Reader;
1515
use Symfony\Component\Serializer\Annotation\DiscriminatorMap;
1616
use Symfony\Component\Serializer\Annotation\Groups;
17+
use Symfony\Component\Serializer\Annotation\Ignore;
1718
use Symfony\Component\Serializer\Annotation\MaxDepth;
1819
use Symfony\Component\Serializer\Annotation\SerializedName;
1920
use Symfony\Component\Serializer\Exception\MappingException;
@@ -71,6 +72,8 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata)
7172
$attributesMetadata[$property->name]->setMaxDepth($annotation->getMaxDepth());
7273
} elseif ($annotation instanceof SerializedName) {
7374
$attributesMetadata[$property->name]->setSerializedName($annotation->getSerializedName());
75+
} elseif ($annotation instanceof Ignore) {
76+
$attributesMetadata[$property->name]->setIgnore(true);
7477
}
7578

7679
$loaded = true;
@@ -116,6 +119,8 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata)
116119
}
117120

118121
$attributeMetadata->setSerializedName($annotation->getSerializedName());
122+
} elseif ($annotation instanceof Ignore) {
123+
$attributeMetadata->setIgnore(true);
119124
}
120125

121126
$loaded = true;

src/Symfony/Component/Serializer/Mapping/Loader/XmlFileLoader.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata)
7070
if (isset($attribute['serialized-name'])) {
7171
$attributeMetadata->setSerializedName((string) $attribute['serialized-name']);
7272
}
73+
74+
if (isset($attribute['ignore'])) {
75+
$attributeMetadata->setIgnore((bool) $attribute['ignore']);
76+
}
7377
}
7478

7579
if (isset($xml->{'discriminator-map'})) {

src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,14 @@ public function loadClassMetadata(ClassMetadataInterface $classMetadata)
9393

9494
$attributeMetadata->setSerializedName($data['serialized_name']);
9595
}
96+
97+
if (isset($data['ignore'])) {
98+
if (!\is_bool($data['ignore'])) {
99+
throw new MappingException(sprintf('The "ignore" value must be a boolean in "%s" for the attribute "%s" of the class "%s".', $this->file, $attribute, $classMetadata->getName()));
100+
}
101+
102+
$attributeMetadata->setIgnore($data['ignore']);
103+
}
96104
}
97105
}
98106

src/Symfony/Component/Serializer/Mapping/Loader/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
</xsd:choice>
4949
<xsd:attribute name="type-property" type="xsd:string" use="required" />
5050
</xsd:complexType>
51-
51+
5252
<xsd:complexType name="discriminator-map-mapping">
5353
<xsd:attribute name="type" type="xsd:string" use="required" />
5454
<xsd:attribute name="class" type="xsd:string" use="required" />
@@ -78,6 +78,7 @@
7878
</xsd:restriction>
7979
</xsd:simpleType>
8080
</xsd:attribute>
81+
<xsd:attribute name="ignore" type="xsd:boolean" />
8182
</xsd:complexType>
8283

8384
</xsd:schema>

src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,22 +239,29 @@ protected function getAllowedAttributes($classOrObject, array $context, bool $at
239239

240240
$tmpGroups = $context[self::GROUPS] ?? $this->defaultContext[self::GROUPS] ?? null;
241241
$groups = (\is_array($tmpGroups) || is_scalar($tmpGroups)) ? (array) $tmpGroups : false;
242-
if (false === $groups && $allowExtraAttributes) {
243-
return false;
244-
}
245242

246243
$allowedAttributes = [];
244+
$ignoreUsed = false;
247245
foreach ($this->classMetadataFactory->getMetadataFor($classOrObject)->getAttributesMetadata() as $attributeMetadata) {
248-
$name = $attributeMetadata->getName();
246+
if ($ignore = $attributeMetadata->isIgnored()) {
247+
$ignoreUsed = true;
248+
}
249249

250+
// If you update this check, update accordingly the one in Symfony\Component\PropertyInfo\Extractor\SerializerExtractor::getProperties()
250251
if (
252+
!$ignore &&
251253
(false === $groups || array_intersect($attributeMetadata->getGroups(), $groups)) &&
252-
$this->isAllowedAttribute($classOrObject, $name, null, $context)
254+
$this->isAllowedAttribute($classOrObject, $name = $attributeMetadata->getName(), null, $context)
253255
) {
254256
$allowedAttributes[] = $attributesAsString ? $name : $attributeMetadata;
255257
}
256258
}
257259

260+
if (!$ignoreUsed && false === $groups && $allowExtraAttributes) {
261+
// Backward Compatibility with the code using this method written before the introduction of @Ignore
262+
return false;
263+
}
264+
258265
return $allowedAttributes;
259266
}
260267

0 commit comments

Comments
 (0)
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