8000 UnwrappingDenormalizer · symfony/symfony@5b757a9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5b757a9

Browse files
committed
UnwrappingDenormalizer
1 parent ad6e888 commit 5b757a9

File tree

4 files changed

+98
-0
lines changed

4 files changed

+98
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
use Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer;
105105
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
106106
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
107+
use Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer;
107108
use Symfony\Component\Stopwatch\Stopwatch;
108109
use Symfony\Component\Translation\Command\XliffLintCommand as BaseXliffLintCommand;
109110
use Symfony\Component\Translation\Translator;
@@ -1454,6 +1455,10 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder
14541455
$container->removeDefinition('serializer.encoder.yaml');
14551456
}
14561457

1458+
if (!class_exists(UnwrappingDenormalizer::class)) {
1459+
$container->removeDefinition('serializer.denormalizer.unwrapping');
1460+
}
1461+
14571462
$serializerLoaders = [];
14581463
if (isset($config['enable_annotations']) && $config['enable_annotations']) {
14591464
if (!$this->annotationsConfigEnabled) {

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@
5959
<tag name="serializer.normalizer" priority="-900" />
6060
</service>
6161

62+
<service id="serializer.denormalizer.unwrapping" class="Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer">
63+
<tag name="serializer.normalizer" priority="1000" />
64+
</service>
65+
6266
<service id="serializer.normalizer.object" class="Symfony\Component\Serializer\Normalizer\ObjectNormalizer">
6367
<argument type="service" id="serializer.mapping.class_metadata_factory" />
6468
<argument type="service" id="serializer.name_converter.metadata_aware" />
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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\PropertyAccess\PropertyAccess;
15+
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
16+
use Symfony\Component\Serializer\SerializerAwareInterface;
17+
use Symfony\Component\Serializer\SerializerInterface;
18+
19+
class UnwrappingDenormalizer implements DenormalizerInterface, SerializerAwareInterface
20+
{
21+
const UNWRAP_PATH = 'unwrap_path';
22+
23+
/**
24+
* @var SerializerInterface|DenormalizerInterface
25+
*/
26+
private $serializer;
27+
28+
/**
29+
* @var PropertyAccess
30+
*/
31+
private $propertyAccess;
32+
33+
public function __construct()
34+
{
35+
$this->propertyAccess = PropertyAccess::createPropertyAccessor();
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*
41+
* @throws NotNormalizableValueException
42+
*/
43+
public function denormalize($data, $class, $format = null, array $context = [])
44+
{
45+
$propertyPath = $context[self::UNWRAP_PATH];
46+
unset($context[self::UNWRAP_PATH]);
47+
48+
if ($propertyPath) {
49+
if (!$this->propertyAccess->isReadable($data, $propertyPath)) {
50+
return null;
51+
}
52+
53+
$data = $this->propertyAccess->getValue($data, $propertyPath);
54+
}
55+
56+
return $this->serializer->denormalize($data, $class, $format, $context);
57+
}
58+
59+
/**
60+
* {@inheritdoc}
61+
*/
62+
public function supportsDenormalization($data, $type, $format = null, array $context = [])
63+
{
64+
return \array_key_exists(self::UNWRAP_PATH, $context);
65+
}
66+
67+
/**
68+
* {@inheritdoc}
69+
*/
70+
public function setSerializer(SerializerInterface $serializer)
71+
{
72+
$this->serializer = $serializer;
73+
}
74+
}

src/Symfony/Component/Serializer/Tests/SerializerTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
3131
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
3232
use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
33+
use Symfony\Component\Serializer\Normalizer\UnwrappingDenormalizer;
3334
use Symfony\Component\Serializer\Serializer;
3435
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummy;
3536
use Symfony\Component\Serializer\Tests\Fixtures\AbstractDummyFirstChild;
@@ -490,6 +491,20 @@ private function serializerWithClassDiscriminator()
490491

491492
return new Serializer([new ObjectNormalizer($classMetadataFactory, null, null, new ReflectionExtractor(), new ClassDiscriminatorFromClassMetadata($classMetadataFactory))], ['json' => new JsonEncoder()]);
492493
}
494+
495+
public function testDeserializeAndUnwrap()
496+
{
497+
$jsonData = '{"baz": {"foo": "bar", "inner": {"title": "value", "numbers": [5,3]}}}';
498+
499+
$expectedData = Model::fromArray(['title' => 'value', 'numbers' => [5, 3]]);
500+
501+
$serializer = new Serializer([new UnwrappingDenormalizer(), new ObjectNormalizer()], ['json' => new JsonEncoder()]);
502+
503+
$this->assertEquals(
504+
$expectedData,
505+
$serializer->deserialize($jsonData, __NAMESPACE__.'\Model', 'json', [UnwrappingDenormalizer::UNWRAP_PATH => '[baz][inner]'])
506+
);
507+
}
493508
}
494509

495510
class Model

0 commit comments

Comments
 (0)
0