[Serializer] fix denormalization of string-arrays with only one element #33731
This commit is contained in:
parent
fda5b20c39
commit
8814751b96
@ -244,16 +244,18 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($type->isCollection() && null !== ($collectionValueType = $type->getCollectionValueType()) && Type::BUILTIN_TYPE_OBJECT === $collectionValueType->getBuiltinType()) {
|
$collectionValueType = $type->isCollection() ? $type->getCollectionValueType() : null;
|
||||||
$builtinType = Type::BUILTIN_TYPE_OBJECT;
|
|
||||||
$class = $collectionValueType->getClassName().'[]';
|
|
||||||
|
|
||||||
// Fix a collection that contains the only one element
|
// Fix a collection that contains the only one element
|
||||||
// This is special to xml format only
|
// This is special to xml format only
|
||||||
if ('xml' === $format && !\is_int(key($data))) {
|
if ('xml' === $format && null !== $collectionValueType && (!\is_array($data) || !\is_int(key($data)))) {
|
||||||
$data = [$data];
|
$data = [$data];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (null !== $collectionValueType && Type::BUILTIN_TYPE_OBJECT === $collectionValueType->getBuiltinType()) {
|
||||||
|
$builtinType = Type::BUILTIN_TYPE_OBJECT;
|
||||||
|
$class = $collectionValueType->getClassName().'[]';
|
||||||
|
|
||||||
if (null !== $collectionKeyType = $type->getCollectionKeyType()) {
|
if (null !== $collectionKeyType = $type->getCollectionKeyType()) {
|
||||||
$context['key_type'] = $collectionKeyType;
|
$context['key_type'] = $collectionKeyType;
|
||||||
}
|
}
|
||||||
|
@ -121,16 +121,54 @@ class AbstractObjectNormalizerTest extends TestCase
|
|||||||
$extractor = $this->getMockBuilder(PhpDocExtractor::class)->getMock();
|
$extractor = $this->getMockBuilder(PhpDocExtractor::class)->getMock();
|
||||||
$extractor->method('getTypes')
|
$extractor->method('getTypes')
|
||||||
->will($this->onConsecutiveCalls(
|
->will($this->onConsecutiveCalls(
|
||||||
[
|
[new Type('array', false, null, true, new Type('int'), new Type('object', false, DummyChild::class))],
|
||||||
new Type(
|
null
|
||||||
'array',
|
));
|
||||||
false,
|
|
||||||
null,
|
$denormalizer = new AbstractObjectNormalizerCollectionDummy(null, null, $extractor);
|
||||||
true,
|
$arrayDenormalizer = new ArrayDenormalizerDummy();
|
||||||
new Type('int'),
|
$serializer = new SerializerCollectionDummy([$arrayDenormalizer, $denormalizer]);
|
||||||
new Type('object', false, DummyChild::class)
|
$arrayDenormalizer->setSerializer($serializer);
|
||||||
),
|
$denormalizer->setSerializer($serializer);
|
||||||
],
|
|
||||||
|
return $denormalizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDenormalizeStringCollectionDecodedFromXmlWithOneChild()
|
||||||
|
{
|
||||||
|
$denormalizer = $this->getDenormalizerForStringCollection();
|
||||||
|
|
||||||
|
// if an xml-node can have children which should be deserialized as string[]
|
||||||
|
// and only one child exists
|
||||||
|
$stringCollection = $denormalizer->denormalize(['children' => 'foo'], StringCollection::class, 'xml');
|
||||||
|
|
||||||
|
$this->assertInstanceOf(StringCollection::class, $stringCollection);
|
||||||
|
$this->assertIsArray($stringCollection->children);
|
||||||
|
$this->assertCount(1, $stringCollection->children);
|
||||||
|
$this->assertEquals('foo', $stringCollection->children[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDenormalizeStringCollectionDecodedFromXmlWithTwoChildren()
|
||||||
|
{
|
||||||
|
$denormalizer = $this->getDenormalizerForStringCollection();
|
||||||
|
|
||||||
|
// if an xml-node can have children which should be deserialized as string[]
|
||||||
|
// and only one child exists
|
||||||
|
$stringCollection = $denormalizer->denormalize(['children' => ['foo', 'bar']], StringCollection::class, 'xml');
|
||||||
|
|
||||||
|
$this->assertInstanceOf(StringCollection::class, $stringCollection);
|
||||||
|
$this->assertIsArray($stringCollection->children);
|
||||||
|
$this->assertCount(2, $stringCollection->children);
|
||||||
|
$this->assertEquals('foo', $stringCollection->children[0]);
|
||||||
|
$this->assertEquals('bar', $stringCollection->children[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDenormalizerForStringCollection()
|
||||||
|
{
|
||||||
|
$extractor = $this->getMockBuilder(PhpDocExtractor::class)->getMock();
|
||||||
|
$extractor->method('getTypes')
|
||||||
|
->will($this->onConsecutiveCalls(
|
||||||
|
[new Type('array', false, null, true, new Type('int'), new Type('string'))],
|
||||||
null
|
null
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -212,6 +250,12 @@ class AbstractObjectNormalizerWithMetadata extends AbstractObjectNormalizer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class StringCollection
|
||||||
|
{
|
||||||
|
/** @var string[] */
|
||||||
|
public $children;
|
||||||
|
}
|
||||||
|
|
||||||
class DummyCollection
|
class DummyCollection
|
||||||
{
|
{
|
||||||
/** @var DummyChild[] */
|
/** @var DummyChild[] */
|
||||||
|
Reference in New Issue
Block a user