[Serializer] Allow multi-dimenstion object array in AbstractObjectNormalizer

This commit is contained in:
Alejandro Diaz Torres 2019-07-31 15:39:27 +02:00 committed by Fabien Potencier
parent dc75ae2614
commit ea03f6d664
2 changed files with 98 additions and 0 deletions

View File

@ -415,6 +415,26 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
if (null !== $collectionKeyType = $type->getCollectionKeyType()) {
$context['key_type'] = $collectionKeyType;
}
} elseif ($type->isCollection() && null !== ($collectionValueType = $type->getCollectionValueType()) && Type::BUILTIN_TYPE_ARRAY === $collectionValueType->getBuiltinType()) {
// get inner type for any nested array
$innerType = $collectionValueType;
// note that it will break for any other builtinType
$dimensions = '[]';
while (null !== $innerType->getCollectionValueType() && Type::BUILTIN_TYPE_ARRAY === $innerType->getBuiltinType()) {
$dimensions .= '[]';
$innerType = $innerType->getCollectionValueType();
}
if (null !== $innerType->getClassName()) {
// the builtinType is the inner one and the class is the class followed by []...[]
$builtinType = $innerType->getBuiltinType();
$class = $innerType->getClassName().$dimensions;
} else {
// default fallback (keep it as array)
$builtinType = $type->getBuiltinType();
$class = $type->getClassName();
}
} else {
$builtinType = $type->getBuiltinType();
$class = $type->getClassName();

View File

@ -27,6 +27,7 @@ use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\Serializer\Tests\Fixtures\Dummy;
use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy;
use Symfony\Component\Serializer\Tests\Fixtures\GroupDummyChild;
use Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy;
@ -407,6 +408,52 @@ class PropertyNormalizerTest extends TestCase
{
$this->assertTrue($this->normalizer->supportsNormalization(new PropertyChildDummy()));
}
public function testMultiDimensionObject()
{
$normalizer = $this->getDenormalizerForTypeEnforcement();
$root = $normalizer->denormalize([
'children' => [[
['foo' => 'one', 'bar' => 'two'],
['foo' => 'three', 'bar' => 'four'],
]],
'grandChildren' => [[[
['foo' => 'five', 'bar' => 'six'],
['foo' => 'seven', 'bar' => 'eight'],
]]],
'intMatrix' => [
[0, 1, 2],
[3, 4, 5],
],
],
RootDummy::class,
'any'
);
$this->assertEquals(\get_class($root), RootDummy::class);
// children (two dimension array)
$this->assertCount(1, $root->children);
$this->assertCount(2, $root->children[0]);
$firstChild = $root->children[0][0];
$this->assertInstanceOf(Dummy::class, $firstChild);
$this->assertSame('one', $firstChild->foo);
$this->assertSame('two', $firstChild->bar);
// grand children (three dimension array)
$this->assertCount(1, $root->grandChildren);
$this->assertCount(1, $root->grandChildren[0]);
$this->assertCount(2, $root->grandChildren[0][0]);
$firstGrandChild = $root->grandChildren[0][0][0];
$this->assertInstanceOf(Dummy::class, $firstGrandChild);
$this->assertSame('five', $firstGrandChild->foo);
$this->assertSame('six', $firstGrandChild->bar);
// int matrix
$this->assertSame([
[0, 1, 2],
[3, 4, 5],
], $root->intMatrix);
}
}
class PropertyDummy
@ -472,3 +519,34 @@ class PropertyParentDummy
class PropertyChildDummy extends PropertyParentDummy
{
}
class RootDummy
{
public $children;
public $grandChildren;
public $intMatrix;
/**
* @return Dummy[][]
*/
public function getChildren(): array
{
return $this->children;
}
/**
* @return Dummy[][][]
*/
public function getGrandChildren()
{
return $this->grandChildren;
}
/**
* @return array
*/
public function getIntMatrix()
{
return $this->intMatrix;
}
}