Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb01db33

Browse files
committed
Add COLLECT_EXTRA_ATTRIBUTES_ERRORS and full deserialization path
1 parentc2af1fd commitb01db33

16 files changed

+346
-29
lines changed

‎UPGRADE-6.2.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ Serializer
9090
* Deprecate calling`AttributeMetadata::setSerializedName()`,`ClassMetadata::setClassDiscriminatorMapping()` without arguments
9191
* Change the signature of`AttributeMetadataInterface::setSerializedName()` to`setSerializedName(?string)`
9292
* Change the signature of`ClassMetadataInterface::setClassDiscriminatorMapping()` to`setClassDiscriminatorMapping(?ClassDiscriminatorMapping)`
93+
* Deprecate`PartialDenormalizationException::getErrors()`, call`getNotNormalizableValueErrors()` instead
9394

9495
Validator
9596
---------

‎src/Symfony/Component/Console/Helper/Table.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ public function setHeaders(array $headers): static
192192
/**
193193
* @return $this
194194
*/
195-
publicfunctionsetRows(array$rows)
195+
publicfunctionsetRows(array$rows):static
196196
{
197197
$this->rows = [];
198198

@@ -251,7 +251,7 @@ public function appendRow(TableSeparator|array $row): static
251251
/**
252252
* @return $this
253253
*/
254-
publicfunctionsetRow(int|string$column,array$row):static
254+
publicfunctionsetRow(int|string$column,array$row)
255255
{
256256
$this->rows[$column] =$row;
257257

‎src/Symfony/Component/PropertyAccess/CHANGELOG.md

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

77
* Deprecate calling`PropertyAccessorBuilder::setCacheItemPool()` without arguments
88
* Added method`isNullSafe()` to`PropertyPathInterface`
9+
* Add`PropertyPath::append()`
910

1011
6.0
1112
---

‎src/Symfony/Component/PropertyAccess/PropertyPath.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,4 +203,33 @@ public function isNullSafe(int $index): bool
203203

204204
return$this->isNullSafe[$index];
205205
}
206+
207+
/**
208+
* Utility method for dealing with property paths.
209+
* For more extensive functionality, use instances of this class.
210+
*
211+
* Appends a path to a given property path.
212+
*
213+
* If the base path is empty, the appended path will be returned unchanged.
214+
* If the base path is not empty, and the appended path starts with a
215+
* squared opening bracket ("["), the concatenation of the two paths is
216+
* returned. Otherwise, the concatenation of the two paths is returned,
217+
* separated by a dot (".").
218+
*/
219+
publicstaticfunctionappend(string$basePath,string$subPath):string
220+
{
221+
if ('' ===$subPath) {
222+
return$basePath;
223+
}
224+
225+
if ('[' ===$subPath[0]) {
226+
return$basePath.$subPath;
227+
}
228+
229+
if ('' ===$basePath) {
230+
return$subPath;
231+
}
232+
233+
return$basePath.'.'.$subPath;
234+
}
206235
}

‎src/Symfony/Component/PropertyAccess/Tests/PropertyPathTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,24 @@ public function testIsIndexDoesNotAcceptNegativeIndices()
170170

171171
$propertyPath->isIndex(-1);
172172
}
173+
174+
/**
175+
* @dataProvider provideAppendPaths
176+
*/
177+
publicfunctiontestAppend(string$basePath,string$subPath,string$expectedPath,string$message)
178+
{
179+
$this->assertSame($expectedPath, PropertyPath::append($basePath,$subPath),$message);
180+
}
181+
182+
publicfunctionprovideAppendPaths()
183+
{
184+
return [
185+
['foo','','foo','It returns the basePath if subPath is empty'],
186+
['','bar','bar','It returns the subPath if basePath is empty'],
187+
['foo','bar','foo.bar','It append the subPath to the basePath'],
188+
['foo','[bar]','foo[bar]','It does not include the dot separator if subPath uses the array notation'],
189+
['0','bar','0.bar','Leading zeros are kept.'],
190+
['0',1,'0.1','Numeric subpaths do not cause PHP 7.4 errors.'],
191+
];
192+
}
173193
}

‎src/Symfony/Component/Serializer/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ CHANGELOG
1111
* Change the signature of`AttributeMetadataInterface::setSerializedName()` to`setSerializedName(?string)`
1212
* Change the signature of`ClassMetadataInterface::setClassDiscriminatorMapping()` to`setClassDiscriminatorMapping(?ClassDiscriminatorMapping)`
1313
* 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.
14+
* Add`COLLECT_EXTRA_ATTRIBUTES_ERRORS` option to`Serializer` to collect errors from nested denormalizations
15+
* Deprecate`PartialDenormalizationException::getErrors()`, call`getNotNormalizableValueErrors()` instead
1416

1517
6.1
1618
---

‎src/Symfony/Component/Serializer/Context/SerializerContextBuilder.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespaceSymfony\Component\Serializer\Context;
1313

14+
useSymfony\Component\Serializer\Normalizer\AbstractNormalizer;
1415
useSymfony\Component\Serializer\Normalizer\DenormalizerInterface;
1516
useSymfony\Component\Serializer\Serializer;
1617

@@ -36,4 +37,9 @@ public function withCollectDenormalizationErrors(?bool $collectDenormalizationEr
3637
{
3738
return$this->with(DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS,$collectDenormalizationErrors);
3839
}
40+
41+
publicfunctionwithCollectExtraAttributesErrors(?bool$collectExtraAttributesErrors):static
42+
{
43+
return$this->with(DenormalizerInterface::COLLECT_EXTRA_ATTRIBUTES_ERRORS,$collectExtraAttributesErrors);
44+
}
3945
}

‎src/Symfony/Component/Serializer/Exception/PartialDenormalizationException.php

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,51 @@
1616
*/
1717
class PartialDenormalizationExceptionextends UnexpectedValueException
1818
{
19-
private$data;
20-
private$errors;
19+
private ?ExtraAttributesException$extraAttributesError =null;
2120

22-
publicfunction__construct($data,array$errors)
21+
publicfunction__construct(
22+
private$data,
23+
/**
24+
* @var NotNormalizableValueException[]
25+
*/
26+
privatearray$notNormalizableErrors,
27+
array$extraAttributesErrors = []
28+
)
2329
{
2430
$this->data =$data;
25-
$this->errors =$errors;
31+
$this->notNormalizableErrors =$notNormalizableErrors;
32+
$extraAttributes = [];
33+
foreach ($extraAttributesErrorsas$error) {
34+
$extraAttributes =\array_merge($extraAttributes,$error->getExtraAttributes());
35+
}
36+
if (\count($extraAttributes) >0) {
37+
$this->extraAttributesError =newExtraAttributesException($extraAttributes);
38+
}
2639
}
2740

2841
publicfunctiongetData()
2942
{
3043
return$this->data;
3144
}
3245

46+
/**
47+
* @deprecated Use getNotNormalizableValueErrors() instead.
48+
*/
3349
publicfunctiongetErrors():array
3450
{
35-
return$this->errors;
51+
return$this->getNotNormalizableValueErrors();
52+
}
53+
54+
/**
55+
* @var NotNormalizableValueException[]
56+
*/
57+
publicfunctiongetNotNormalizableValueErrors():array
58+
{
59+
return$this->notNormalizableErrors;
60+
}
61+
62+
publicfunctiongetExtraAttributesError(): ?ExtraAttributesException
63+
{
64+
return$this->extraAttributesError;
3665
}
3766
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespaceSymfony\Component\Serializer\Normalizer;
1313

14+
useSymfony\Component\PropertyAccess\PropertyPath;
1415
useSymfony\Component\Serializer\Exception\CircularReferenceException;
1516
useSymfony\Component\Serializer\Exception\InvalidArgumentException;
1617
useSymfony\Component\Serializer\Exception\LogicException;
@@ -505,7 +506,7 @@ protected function getAttributeNormalizationContext(object $object, string $attr
505506
*/
506507
protectedfunctiongetAttributeDenormalizationContext(string$class,string$attribute,array$context):array
507508
{
508-
$context['deserialization_path'] = ($context['deserialization_path'] ??false) ?$context['deserialization_path'].'.'.$attribute :$attribute;
509+
$context['deserialization_path'] =PropertyPath::append($context['deserialization_path'] ??'',$attribute);
509510

510511
if (null ===$metadata =$this->getAttributeMetadata($class,$attribute)) {
511512
return$context;

‎src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
useSymfony\Component\PropertyAccess\Exception\InvalidArgumentException;
1515
useSymfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
1616
useSymfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
17+
useSymfony\Component\PropertyAccess\PropertyPath;
1718
useSymfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
1819
useSymfony\Component\PropertyInfo\Type;
1920
useSymfony\Component\Serializer\Encoder\CsvEncoder;
@@ -225,12 +226,12 @@ protected function instantiateObject(array &$data, string $class, array &$contex
225226
{
226227
if ($this->classDiscriminatorResolver &&$mapping =$this->classDiscriminatorResolver->getMappingForClass($class)) {
227228
if (!isset($data[$mapping->getTypeProperty()])) {
228-
throw NotNormalizableValueException::createForUnexpectedDataType(sprintf('Type property "%s" not found for the abstract object "%s".',$mapping->getTypeProperty(),$class),null, ['string'],isset($context['deserialization_path']) ?$context['deserialization_path'].'.'.$mapping->getTypeProperty() :$mapping->getTypeProperty(),false);
229+
throw NotNormalizableValueException::createForUnexpectedDataType(sprintf('Type property "%s" not found for the abstract object "%s".',$mapping->getTypeProperty(),$class),null, ['string'],PropertyPath::append($context['deserialization_path'] ??'',$mapping->getTypeProperty()),false);
229230
}
230231

231232
$type =$data[$mapping->getTypeProperty()];
232233
if (null === ($mappedClass =$mapping->getClassForType($type))) {
233-
throw NotNormalizableValueException::createForUnexpectedDataType(sprintf('The type "%s" is not a valid value.',$type),$type, ['string'],isset($context['deserialization_path']) ?$context['deserialization_path'].'.'.$mapping->getTypeProperty() :$mapping->getTypeProperty(),true);
234+
throw NotNormalizableValueException::createForUnexpectedDataType(sprintf('The type "%s" is not a valid value.',$type),$type, ['string'],PropertyPath::append($context['deserialization_path'] ??'',$mapping->getTypeProperty()),true);
234235
}
235236

236237
if ($mappedClass !==$class) {
@@ -378,8 +379,12 @@ public function denormalize(mixed $data, string $type, string $format = null, ar
378379
}
379380
}
380381

381-
if ($extraAttributes) {
382-
thrownewExtraAttributesException($extraAttributes);
382+
if (!$extraAttributes) {
383+
$extraAttributeException =newExtraAttributesException(array_map(fn (string$extraAttribute) => PropertyPath::append($context['deserialization_path'] ??'',$extraAttribute),$extraAttributes));
384+
if (!isset($context['extra_attributes_exceptions'])) {
385+
throw$extraAttributeException;
386+
}
387+
$context['extra_attributes_exceptions'][] =$extraAttributeException;
383388
}
384389

385390
return$object;

‎src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespaceSymfony\Component\Serializer\Normalizer;
1313

14+
useSymfony\Component\PropertyAccess\PropertyPath;
1415
useSymfony\Component\PropertyInfo\Type;
1516
useSymfony\Component\Serializer\Exception\BadMethodCallException;
1617
useSymfony\Component\Serializer\Exception\InvalidArgumentException;
@@ -47,7 +48,7 @@ public function denormalize(mixed $data, string $type, string $format = null, ar
4748
$builtinType =isset($context['key_type']) ?$context['key_type']->getBuiltinType() :null;
4849
foreach ($dataas$key =>$value) {
4950
$subContext =$context;
50-
$subContext['deserialization_path'] = ($context['deserialization_path'] ??false) ?sprintf('%s[%s]',$context['deserialization_path'],$key) :"[$key]";
51+
$subContext['deserialization_path'] =PropertyPath::append($context['deserialization_path'] ??'',"[$key]");
5152

5253
if (null !==$builtinType && !('is_'.$builtinType)($key)) {
5354
throw NotNormalizableValueException::createForUnexpectedDataType(sprintf('The type of the key "%s" must be "%s" ("%s" given).',$key,$builtinType,get_debug_type($key)),$key, [$builtinType],$subContext['deserialization_path'] ??null,true);

‎src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,16 @@
2424
*/
2525
interface DenormalizerInterface
2626
{
27+
/**
28+
* Whether to collect all denormalization errors or to stop at first error.
29+
*/
2730
publicconstCOLLECT_DENORMALIZATION_ERRORS ='collect_denormalization_errors';
2831

32+
/**
33+
* Whether to collect all extra attributes errors or to stop at first nested error.
34+
*/
35+
publicconstCOLLECT_EXTRA_ATTRIBUTES_ERRORS ='collect_extra_attributes_errors';
36+
2937
/**
3038
* Denormalizes data back into an object of the given class.
3139
*

‎src/Symfony/Component/Serializer/Serializer.php

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -212,19 +212,27 @@ public function denormalize(mixed $data, string $type, string $format = null, ar
212212
thrownewNotNormalizableValueException(sprintf('Could not denormalize object of type "%s", no supporting normalizer found.',$type));
213213
}
214214

215-
if (isset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS])) {
216-
unset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS]);
215+
$notNormalizableExceptions = [];
216+
if($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS] ??false) {
217217
$context['not_normalizable_value_exceptions'] = [];
218-
$errors = &$context['not_normalizable_value_exceptions'];
219-
$denormalized =$normalizer->denormalize($data,$type,$format,$context);
220-
if ($errors) {
221-
thrownewPartialDenormalizationException($denormalized,$errors);
222-
}
218+
$notNormalizableExceptions = &$context['not_normalizable_value_exceptions'];
219+
}
220+
unset($context[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS]);
221+
222+
$extraAttributesExceptions = [];
223+
if ($context[DenormalizerInterface::COLLECT_EXTRA_ATTRIBUTES_ERRORS] ??false) {
224+
$context['extra_attributes_exceptions'] = [];
225+
$extraAttributesExceptions = &$context['extra_attributes_exceptions'];
226+
}
227+
unset($context[DenormalizerInterface::COLLECT_EXTRA_ATTRIBUTES_ERRORS]);
228+
229+
$denormalized =$normalizer->denormalize($data,$type,$format,$context);
223230

224-
return$denormalized;
231+
if (\count($notNormalizableExceptions) >0 ||\count($extraAttributesExceptions) >0) {
232+
thrownewPartialDenormalizationException($denormalized,$notNormalizableExceptions,$extraAttributesExceptions);
225233
}
226234

227-
return$normalizer->denormalize($data,$type,$format,$context);
235+
return$denormalized;
228236
}
229237

230238
publicfunctionsupportsNormalization(mixed$data,string$format =null,array$context = []):bool

‎src/Symfony/Component/Serializer/Tests/Context/SerializerContextBuilderTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
usePHPUnit\Framework\TestCase;
1515
useSymfony\Component\Serializer\Context\SerializerContextBuilder;
16+
useSymfony\Component\Serializer\Normalizer\AbstractNormalizer;
1617
useSymfony\Component\Serializer\Normalizer\DenormalizerInterface;
1718
useSymfony\Component\Serializer\Serializer;
1819

@@ -38,6 +39,7 @@ public function testWithers(array $values)
3839
$context =$this->contextBuilder
3940
->withEmptyArrayAsObject($values[Serializer::EMPTY_ARRAY_AS_OBJECT])
4041
->withCollectDenormalizationErrors($values[DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS])
42+
->withCollectExtraAttributesErrors($values[DenormalizerInterface::COLLECT_EXTRA_ATTRIBUTES_ERRORS])
4143
->toArray();
4244

4345
$this->assertSame($values,$context);
@@ -51,11 +53,13 @@ public function withersDataProvider(): iterable
5153
yield'With values' => [[
5254
Serializer::EMPTY_ARRAY_AS_OBJECT =>true,
5355
DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS =>false,
56+
DenormalizerInterface::COLLECT_EXTRA_ATTRIBUTES_ERRORS =>false,
5457
]];
5558

5659
yield'With null values' => [[
5760
Serializer::EMPTY_ARRAY_AS_OBJECT =>null,
5861
DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS =>null,
62+
DenormalizerInterface::COLLECT_EXTRA_ATTRIBUTES_ERRORS =>null,
5963
]];
6064
}
6165
}

‎src/Symfony/Component/Serializer/Tests/Fixtures/Php74Full.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ final class Php74Full
3333
publicTestFoo$nestedObject;
3434
/** @var Php74Full[] */
3535
public$anotherCollection;
36+
publicTestFoo$nestedObject2;
3637
}
3738

3839

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp