Skip to content

Commit a2cd56c

Browse files
bug #33733 [Serializer] fix denormalization of string-arrays with only one element (mkrauser)
This PR was merged into the 3.4 branch. Discussion ---------- [Serializer] fix denormalization of string-arrays with only one element | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? |no | Deprecations? |no | Tickets | Fix #33731 | License | MIT | Doc PR | This PR does almost the same as ac70edf, just not only for arrays of objects. Commits ------- 8814751 [Serializer] fix denormalization of string-arrays with only one element #33731
2 parents 03f2adc + 8814751 commit a2cd56c

File tree

2 files changed

+63
-17
lines changed

2 files changed

+63
-17
lines changed

src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -244,16 +244,18 @@ private function validateAndDenormalize($currentClass, $attribute, $data, $forma
244244
return null;
245245
}
246246

247-
if ($type->isCollection() && null !== ($collectionValueType = $type->getCollectionValueType()) && Type::BUILTIN_TYPE_OBJECT === $collectionValueType->getBuiltinType()) {
247+
$collectionValueType = $type->isCollection() ? $type->getCollectionValueType() : null;
248+
249+
// Fix a collection that contains the only one element
250+
// This is special to xml format only
251+
if ('xml' === $format && null !== $collectionValueType && (!\is_array($data) || !\is_int(key($data)))) {
252+
$data = [$data];
253+
}
254+
255+
if (null !== $collectionValueType && Type::BUILTIN_TYPE_OBJECT === $collectionValueType->getBuiltinType()) {
248256
$builtinType = Type::BUILTIN_TYPE_OBJECT;
249257
$class = $collectionValueType->getClassName().'[]';
250258

251-
// Fix a collection that contains the only one element
252-
// This is special to xml format only
253-
if ('xml' === $format && !\is_int(key($data))) {
254-
$data = [$data];
255-
}
256-
257259
if (null !== $collectionKeyType = $type->getCollectionKeyType()) {
258260
$context['key_type'] = $collectionKeyType;
259261
}

src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,54 @@ private function getDenormalizerForDummyCollection()
121121
$extractor = $this->getMockBuilder(PhpDocExtractor::class)->getMock();
122122
$extractor->method('getTypes')
123123
->will($this->onConsecutiveCalls(
124-
[
125-
new Type(
126-
'array',
127-
false,
128-
null,
129-
true,
130-
new Type('int'),
131-
new Type('object', false, DummyChild::class)
132-
),
133-
],
124+
[new Type('array', false, null, true, new Type('int'), new Type('object', false, DummyChild::class))],
125+
null
126+
));
127+
128+
$denormalizer = new AbstractObjectNormalizerCollectionDummy(null, null, $extractor);
129+
$arrayDenormalizer = new ArrayDenormalizerDummy();
130+
$serializer = new SerializerCollectionDummy([$arrayDenormalizer, $denormalizer]);
131+
$arrayDenormalizer->setSerializer($serializer);
132+
$denormalizer->setSerializer($serializer);
133+
134+
return $denormalizer;
135+
}
136+
137+
public function testDenormalizeStringCollectionDecodedFromXmlWithOneChild()
138+
{
139+
$denormalizer = $this->getDenormalizerForStringCollection();
140+
141+
// if an xml-node can have children which should be deserialized as string[]
142+
// and only one child exists
143+
$stringCollection = $denormalizer->denormalize(['children' => 'foo'], StringCollection::class, 'xml');
144+
145+
$this->assertInstanceOf(StringCollection::class, $stringCollection);
146+
$this->assertIsArray($stringCollection->children);
147+
$this->assertCount(1, $stringCollection->children);
148+
$this->assertEquals('foo', $stringCollection->children[0]);
149+
}
150+
151+
public function testDenormalizeStringCollectionDecodedFromXmlWithTwoChildren()
152+
{
153+
$denormalizer = $this->getDenormalizerForStringCollection();
154+
155+
// if an xml-node can have children which should be deserialized as string[]
156+
// and only one child exists
157+
$stringCollection = $denormalizer->denormalize(['children' => ['foo', 'bar']], StringCollection::class, 'xml');
158+
159+
$this->assertInstanceOf(StringCollection::class, $stringCollection);
160+
$this->assertIsArray($stringCollection->children);
161+
$this->assertCount(2, $stringCollection->children);
162+
$this->assertEquals('foo', $stringCollection->children[0]);
163+
$this->assertEquals('bar', $stringCollection->children[1]);
164+
}
165+
166+
private function getDenormalizerForStringCollection()
167+
{
168+
$extractor = $this->getMockBuilder(PhpDocExtractor::class)->getMock();
169+
$extractor->method('getTypes')
170+
->will($this->onConsecutiveCalls(
171+
[new Type('array', false, null, true, new Type('int'), new Type('string'))],
134172
null
135173
));
136174

@@ -212,6 +250,12 @@ protected function setAttributeValue($object, $attribute, $value, $format = null
212250
}
213251
}
214252

253+
class StringCollection
254+
{
255+
/** @var string[] */
256+
public $children;
257+
}
258+
215259
class DummyCollection
216260
{
217261
/** @var DummyChild[] */

0 commit comments

Comments
 (0)
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