Description
Heyho,
I currently work on a problem when using the ObjectNormalizer with an multidimensional array as input. My array looks like this:
[
'base_property1' => 'value123',
'nested_resources' => [
[
'nested_property' => 'value1234'
],
[
'nested_property' => 'value2345'
],
]
]
I defined the following classes the data of this array should be passed to:
class Resource {
/**
* @var string
*/
private $baseProperty1;
/**
* @var nestedResource[]|ArrayCollection
*/
private $nestedResources;
public function getBaseProperty1() {
return $this->baseProperty1;
}
public function setBaseProperty1($baseProperty1) {
$this->baseProperty1 = $baseProperty1;
return $this;
}
public function getNestedResources() {
return $this->nestedResources;
}
public function setNestedResources($nestedResources) {
$this->nestedResources = $nestedResources;
return $this;
}
}
class NestedResource {
/**
* @var string
*/
private $nestedProperty;
public function getNestedProperty() {
return $this->nestedProperty;
}
public function setNestedProperty($nestedProperty) {
$this->nestedProperty = $nestedProperty;
return $this;
}
}
When using the Serializer-Component of Symfony to denormalize the input-array I expected to get the following result:
Resource {
-baseProperty1: "value123"
-nestedResources: array:2 [
0 => NestedResource {
-nestedProperty: 'value1234'
}
2 => NestedResource {
-nestedProperty: 'value2345'
}
]
}
but instead I get the following:
Resource {
-baseProperty1: "value123"
-nestedResources: array:2 [
0 => array [
nestedProperty => 'value1234'
}
1 => array [
nestedProperty => 'value2345'
}
]
}
I defined the following services to get a serializer-service using the ReflectionExtrator:
services:
name_converter.camel_case_to_sneak_case_name:
class: Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter
property_accessor.reflection:
class: Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor
denormalizer.array:
class: Symfony\Component\Serializer\Normalizer\ArrayDenormalizer
normalizer.object:
class: Symfony\Component\Serializer\Normalizer\ObjectNormalizer
arguments:
-
- "@name_converter.camel_case_to_sneak_case_name"
-
- "@property_accessor.reflection"
encoder.json:
class: Symfony\Component\Serializer\Encoder\JsonEncoder
serializer:
class: Symfony\Component\Serializer\Serializer
arguments:
- ["@normalizer.object", "@denormalizer.array"]
- ["@encoder.json"]
I tested it with latest Symfony 3.1.3. I think the issue occures because of a missing check for a collection in class AbstractObjectNormalizer
in line 255 to 263. It is only checked for an object, but if $type
is an collection this is not honored. I get a correct result if I add the following check just before line 255, but I think this is not a nice solution because of the need to add brackets after the class-name:
if ($type->isCollection() && $type->getCollectionValueType()->getBuiltinType() === Type::BUILTIN_TYPE_OBJECT) {
$class = $type->getCollectionValueType()->getClassName() . '[]';
$builtinType = $type->getCollectionValueType()->getBuiltinType();
}
I get the same result with PhpDocExtractor.