Skip to content

Commit 80e172d

Browse files
Merge branch '3.1'
* 3.1: [travis] Use 7.0 until 7.1 is fixed [DIC] Fix service autowiring inheritance [Serializer] Fix denormalization of arrays [SecurityBundle] Add missing deprecation notice for form_login.intention Verify explicitly that the request IP is a valid IPv4 address [WebProfilerBundle] replaces tabs characters by spaces.
2 parents 62206e0 + 81674b4 commit 80e172d

File tree

4 files changed

+70
-13
lines changed

4 files changed

+70
-13
lines changed

Normalizer/AbstractObjectNormalizer.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,18 @@ private function validateAndDenormalize($currentClass, $attribute, $data, $forma
248248
return;
249249
}
250250

251-
$builtinType = $type->getBuiltinType();
252-
$class = $type->getClassName();
251+
if ($type->isCollection() && null !== ($collectionValueType = $type->getCollectionValueType()) && Type::BUILTIN_TYPE_OBJECT === $collectionValueType->getBuiltinType()) {
252+
$builtinType = Type::BUILTIN_TYPE_OBJECT;
253+
$class = $collectionValueType->getClassName().'[]';
254+
255+
if (null !== $collectionKeyType = $type->getCollectionKeyType()) {
256+
$context['key_type'] = $collectionKeyType;
257+
}
258+
} else {
259+
$builtinType = $type->getBuiltinType();
260+
$class = $type->getClassName();
261+
}
262+
253263
$expectedTypes[Type::BUILTIN_TYPE_OBJECT === $builtinType && $class ? $class : $builtinType] = true;
254264

255265
if (Type::BUILTIN_TYPE_OBJECT === $builtinType) {

Normalizer/ArrayDenormalizer.php

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

1414
use Symfony\Component\Serializer\Exception\BadMethodCallException;
1515
use Symfony\Component\Serializer\Exception\InvalidArgumentException;
16+
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
1617
use Symfony\Component\Serializer\SerializerAwareInterface;
1718
use Symfony\Component\Serializer\SerializerInterface;
1819

@@ -30,6 +31,8 @@ class ArrayDenormalizer implements DenormalizerInterface, SerializerAwareInterfa
3031

3132
/**
3233
* {@inheritdoc}
34+
*
35+
* @throws UnexpectedValueException
3336
*/
3437
public function denormalize($data, $class, $format = null, array $context = array())
3538
{
@@ -46,12 +49,16 @@ public function denormalize($data, $class, $format = null, array $context = arra
4649
$serializer = $this->serializer;
4750
$class = substr($class, 0, -2);
4851

49-
return array_map(
50-
function ($data) use ($serializer, $class, $format, $context) {
51-
return $serializer->denormalize($data, $class, $format, $context);
52-
},
53-
$data
54-
);
52+
$builtinType = isset($context['key_type']) ? $context['key_type']->getBuiltinType() : null;
53+
foreach ($data as $key => $value) {
54+
if (null !== $builtinType && !call_user_func('is_'.$builtinType, $key)) {
55+
throw new UnexpectedValueException(sprintf('The type of the key "%s" must be "%s" ("%s" given).', $key, $builtinType, gettype($key)));
56+
}
57+
58+
$data[$key] = $serializer->denormalize($value, $class, $format, $context);
59+
}
60+
61+
return $data;
5562
}
5663

5764
/**

Tests/Normalizer/ObjectNormalizerTest.php

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@
1212
namespace Symfony\Component\Serializer\Tests\Normalizer;
1313

1414
use Doctrine\Common\Annotations\AnnotationReader;
15+
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
1516
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
17+
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
1618
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
1719
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
20+
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
1821
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
1922
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
2023
use Symfony\Component\Serializer\Serializer;
@@ -569,13 +572,21 @@ public function testThrowUnexpectedValueException()
569572

570573
public function testDenomalizeRecursive()
571574
{
572-
$normalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor());
573-
$serializer = new Serializer(array(new DateTimeNormalizer(), $normalizer));
575+
$extractor = new PropertyInfoExtractor(array(), array(new PhpDocExtractor(), new ReflectionExtractor()));
576+
$normalizer = new ObjectNormalizer(null, null, null, $extractor);
577+
$serializer = new Serializer(array(new ArrayDenormalizer(), new DateTimeNormalizer(), $normalizer));
578+
579+
$obj = $serializer->denormalize(array(
580+
'inner' => array('foo' => 'foo', 'bar' => 'bar'),
581+
'date' => '1988/01/21',
582+
'inners' => array(array('foo' => 1), array('foo' => 2)),
583+
), ObjectOuter::class);
574584

575-
$obj = $serializer->denormalize(array('inner' => array('foo' => 'foo', 'bar' => 'bar'), 'date' => '1988/01/21'), ObjectOuter::class);
576585
$this->assertEquals('foo', $obj->getInner()->foo);
577586
$this->assertEquals('bar', $obj->getInner()->bar);
578587
$this->assertEquals('1988-01-21', $obj->getDate()->format('Y-m-d'));
588+
$this->assertEquals(1, $obj->getInners()[0]->foo);
589+
$this->assertEquals(2, $obj->getInners()[1]->foo);
579590
}
580591

581592
/**
@@ -590,6 +601,19 @@ public function testRejectInvalidType()
590601
$serializer->denormalize(array('date' => 'foo'), ObjectOuter::class);
591602
}
592603

604+
/**
605+
* @expectedException UnexpectedValueException
606+
* @expectedExceptionMessage The type of the key "a" must be "int" ("string" given).
607+
*/
608+
public function testRejectInvalidKey()
609+
{
610+
$extractor = new PropertyInfoExtractor(array(), array(new PhpDocExtractor(), new ReflectionExtractor()));
611+
$normalizer = new ObjectNormalizer(null, null, null, $extractor);
612+
$serializer = new Serializer(array(new ArrayDenormalizer(), new DateTimeNormalizer(), $normalizer));
613+
614+
$serializer->denormalize(array('inners' => array('a' => array('foo' => 1))), ObjectOuter::class);
615+
}
616+
593617
public function testExtractAttributesRespectsFormat()
594618
{
595619
$normalizer = new FormatAndContextAwareNormalizer();
@@ -784,6 +808,11 @@ class ObjectOuter
784808
private $inner;
785809
private $date;
786810

811+
/**
812+
* @var ObjectInner[]
813+
*/
814+
private $inners;
815+
787816
public function getInner()
788817
{
789818
return $this->inner;
@@ -803,6 +832,16 @@ public function getDate()
803832
{
804833
return $this->date;
805834
}
835+
836+
public function setInners(array $inners)
837+
{
838+
$this->inners = $inners;
839+
}
840+
841+
public function getInners()
842+
{
843+
return $this->inners;
844+
}
806845
}
807846

808847
class ObjectInner

composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@
2424
"symfony/property-access": "~2.8|~3.0",
2525
"symfony/http-foundation": "~2.8|~3.0",
2626
"symfony/cache": "~3.1",
27-
"symfony/property-info": "~2.8|~3.0",
27+
"symfony/property-info": "~3.1",
2828
"doctrine/annotations": "~1.0",
29-
"doctrine/cache": "~1.0"
29+
"doctrine/cache": "~1.0",
30+
"phpdocumentor/reflection-docblock": "~3.0"
3031
},
3132
"conflict": {
3233
"symfony/property-access": ">=3.0,<3.0.4|>=2.8,<2.8.4"

0 commit comments

Comments
 (0)