diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 2a8018dc0b1bc..9ff231e7a426c 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -248,8 +248,18 @@ private function validateAndDenormalize($currentClass, $attribute, $data, $forma return; } - $builtinType = $type->getBuiltinType(); - $class = $type->getClassName(); + if ($type->isCollection() && null !== ($collectionValueType = $type->getCollectionValueType()) && Type::BUILTIN_TYPE_OBJECT === $collectionValueType->getBuiltinType()) { + $builtinType = Type::BUILTIN_TYPE_OBJECT; + $class = $collectionValueType->getClassName().'[]'; + + if (null !== $collectionKeyType = $type->getCollectionKeyType()) { + $context['key_type'] = $collectionKeyType; + } + } else { + $builtinType = $type->getBuiltinType(); + $class = $type->getClassName(); + } + $expectedTypes[Type::BUILTIN_TYPE_OBJECT === $builtinType && $class ? $class : $builtinType] = true; if (Type::BUILTIN_TYPE_OBJECT === $builtinType) { diff --git a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php index 921e312bd0de9..7d3d87c510c55 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php @@ -13,6 +13,7 @@ use Symfony\Component\Serializer\Exception\BadMethodCallException; use Symfony\Component\Serializer\Exception\InvalidArgumentException; +use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\SerializerAwareInterface; use Symfony\Component\Serializer\SerializerInterface; @@ -30,6 +31,8 @@ class ArrayDenormalizer implements DenormalizerInterface, SerializerAwareInterfa /** * {@inheritdoc} + * + * @throws UnexpectedValueException */ public function denormalize($data, $class, $format = null, array $context = array()) { @@ -46,12 +49,16 @@ public function denormalize($data, $class, $format = null, array $context = arra $serializer = $this->serializer; $class = substr($class, 0, -2); - return array_map( - function ($data) use ($serializer, $class, $format, $context) { - return $serializer->denormalize($data, $class, $format, $context); - }, - $data - ); + $builtinType = isset($context['key_type']) ? $context['key_type']->getBuiltinType() : null; + foreach ($data as $key => $value) { + if (null !== $builtinType && !call_user_func('is_'.$builtinType, $key)) { + throw new UnexpectedValueException(sprintf('The type of the key "%s" must be "%s" ("%s" given).', $key, $builtinType, gettype($key))); + } + + $data[$key] = $serializer->denormalize($value, $class, $format, $context); + } + + return $data; } /** diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index 8a09e516cd230..ca1c4e0f59f82 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -12,9 +12,12 @@ namespace Symfony\Component\Serializer\Tests\Normalizer; use Doctrine\Common\Annotations\AnnotationReader; +use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor; use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; +use Symfony\Component\PropertyInfo\PropertyInfoExtractor; use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; +use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Serializer; @@ -525,13 +528,21 @@ public function testThrowUnexpectedValueException() public function testDenomalizeRecursive() { - $normalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor()); - $serializer = new Serializer(array(new DateTimeNormalizer(), $normalizer)); + $extractor = new PropertyInfoExtractor(array(), array(new PhpDocExtractor(), new ReflectionExtractor())); + $normalizer = new ObjectNormalizer(null, null, null, $extractor); + $serializer = new Serializer(array(new ArrayDenormalizer(), new DateTimeNormalizer(), $normalizer)); + + $obj = $serializer->denormalize(array( + 'inner' => array('foo' => 'foo', 'bar' => 'bar'), + 'date' => '1988/01/21', + 'inners' => array(array('foo' => 1), array('foo' => 2)), + ), ObjectOuter::class); - $obj = $serializer->denormalize(array('inner' => array('foo' => 'foo', 'bar' => 'bar'), 'date' => '1988/01/21'), ObjectOuter::class); $this->assertEquals('foo', $obj->getInner()->foo); $this->assertEquals('bar', $obj->getInner()->bar); $this->assertEquals('1988-01-21', $obj->getDate()->format('Y-m-d')); + $this->assertEquals(1, $obj->getInners()[0]->foo); + $this->assertEquals(2, $obj->getInners()[1]->foo); } /** @@ -546,6 +557,19 @@ public function testRejectInvalidType() $serializer->denormalize(array('date' => 'foo'), ObjectOuter::class); } + /** + * @expectedException UnexpectedValueException + * @expectedExceptionMessage The type of the key "a" must be "int" ("string" given). + */ + public function testRejectInvalidKey() + { + $extractor = new PropertyInfoExtractor(array(), array(new PhpDocExtractor(), new ReflectionExtractor())); + $normalizer = new ObjectNormalizer(null, null, null, $extractor); + $serializer = new Serializer(array(new ArrayDenormalizer(), new DateTimeNormalizer(), $normalizer)); + + $serializer->denormalize(array('inners' => array('a' => array('foo' => 1))), ObjectOuter::class); + } + public function testExtractAttributesRespectsFormat() { $normalizer = new FormatAndContextAwareNormalizer(); @@ -740,6 +764,11 @@ class ObjectOuter private $inner; private $date; + /** + * @var ObjectInner[] + */ + private $inners; + public function getInner() { return $this->inner; @@ -759,6 +788,16 @@ public function getDate() { return $this->date; } + + public function setInners(array $inners) + { + $this->inners = $inners; + } + + public function getInners() + { + return $this->inners; + } } class ObjectInner diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index 29d40aab0293a..01fc76bab53e0 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -24,9 +24,10 @@ "symfony/property-access": "~2.8|~3.0", "symfony/http-foundation": "~2.8|~3.0", "symfony/cache": "~3.1", - "symfony/property-info": "~2.8|~3.0", + "symfony/property-info": "~3.1", "doctrine/annotations": "~1.0", - "doctrine/cache": "~1.0" + "doctrine/cache": "~1.0", + "phpdocumentor/reflection-docblock": "~3.0" }, "conflict": { "symfony/property-access": ">=3.0,<3.0.4|>=2.8,<2.8.4" 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