8000 bug #59308 [JsonEncoder] Fix encoding of dictionary with integer keys… · symfony/symfony@e1a443c · GitHub
[go: up one dir, main page]

Skip to content

Commit e1a443c

committed
bug #59308 [JsonEncoder] Fix encoding of dictionary with integer keys (mtarld)
This PR was merged into the 7.3 branch. Discussion ---------- [JsonEncoder] Fix encoding of dictionary with integer keys | Q | A | ------------- | --- | Branch? | 7.3 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | | License | MIT Fix encoding of dictionary with integer keys. Previously, `[1 => true, 2 => false]` was encoded to `{"": true, "": false}`, now it is encoded to `{"1": true, "2": false}`. Also improve test coverage about list, dictionaries and iterable. Commits ------- 9983379 [JsonEncoder] Fix associative collection consideration
2 parents 8fde3ea + 9983379 commit e1a443c

14 files changed

+122
-39
lines changed

src/Symfony/Component/JsonEncoder/Encode/PhpAstBuilder.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,13 +196,17 @@ private function buildClosureStatements(DataModelNodeInterface $dataModelNode, a
196196
];
197197
}
198198

199+
$escapedKey = $dataModelNode->getType()->getCollectionKeyType()->isIdentifiedBy(TypeIdentifier::INT)
200+
? new Ternary($this->builder->funcCall('is_int', [$this->builder->var('key')]), $this->builder->var('key'), $this->escapeString($this->builder->var('key')))
201+
: $this->escapeString($this->builder->var('key'));
202+
199203
return [
200204
new Expression(new Yield_($this->builder->val('{'))),
201205
new Expression(new Assign($this->builder->var('prefix'), $this->builder->val(''))),
202206
new Foreach_($accessor, $dataModelNode->getItemNode()->getAccessor()->toPhpExpr(), [
203207
'keyVar' => $this->builder->var('key'),
204208
'stmts' => [
205-
new Expression(new Assign($this->builder->var('key'), $this->escapeString($this->builder->var('key')))),
209+
new Expression(new Assign($this->builder->var('key'), $escapedKey)),
206210
new Expression(new Yield_(new Encapsed([
207211
$this->builder->var('prefix'),
208212
new EncapsedStringPart('"'),

src/Symfony/Component/JsonEncoder/Tests/Decode/DecoderGeneratorTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,13 @@ public static function generatedDecoderDataProvider(): iterable
9595
yield ['list', Type::list()];
9696
yield ['object_list', Type::list(Type::object(ClassicDummy::class))];
9797
yield ['nullable_object_list', Type::nullable(Type::list(Type::object(ClassicDummy::class)))];
98-
yield ['iterable_list', Type::it 8000 erable(key: Type::int(), asList: true)];
9998

10099
yield ['dict', Type::dict()];
101100
yield ['object_dict', Type::dict(Type::object(ClassicDummy::class))];
102101
yield ['nullable_object_dict', Type::nullable(Type::dict(Type::object(ClassicDummy::class)))];
103-
yield ['iterable_dict', Type::iterable(key: Type::string())];
102+
103+
yield ['iterable', Type::iterable()];
104+
yield ['object_iterable', Type::iterable(Type::object(ClassicDummy::class))];
104105

105106
yield ['object', Type::object(ClassicDummy::class)];
106107
yield ['nullable_object', Type::nullable(Type::object(ClassicDummy::class))];

src/Symfony/Component/JsonEncoder/Tests/Encode/EncoderGeneratorTest.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Symfony\Component\JsonEncoder\Mapping\PropertyMetadataLoaderInterface;
2222
use Symfony\Component\JsonEncoder\Tests\Fixtures\Enum\DummyBackedEnum;
2323
use Symfony\Component\JsonEncoder\Tests\Fixtures\Enum\DummyEnum;
24+
use Symfony\Component\JsonEncoder\Tests\Fixtures\Model\ClassicDummy;
2425
use Symfony\Component\JsonEncoder\Tests\Fixtures\Model\DummyWithNameAttributes;
2526
use Symfony\Component\JsonEncoder\Tests\Fixtures\Model\DummyWithNormalizerAttributes;
2627
use Symfony\Component\JsonEncoder\Tests\Fixtures\Model\DummyWithOtherDummies;
@@ -92,12 +93,12 @@ public static function generatedEncoderDataProvider(): iterable
9293
yield ['object_list', Type::list(Type::object(DummyWithNameAttributes::class))];
9394
yield ['nullable_object_list', Type::nullable(Type::list(Type::object(DummyWithNameAttributes::class)))];
9495

95-
yield ['iterable_list', Type::iterable(key: Type::int(), asList: true)];
96-
9796
yield ['dict', Type::dict()];
9897
yield ['object_dict', Type::dict(Type::object(DummyWithNameAttributes::class))];
9998
yield ['nullable_object_dict', Type::nullable(Type::dict(Type::object(DummyWithNameAttributes::class)))];
100-
yield ['iterable_dict', Type::iterable(key: Type::string())];
99+
100+
yield ['iterable', Type::iterable()];
101+
yield ['object_iterable', Type::iterable(Type::object(ClassicDummy::class))];
101102

102103
yield ['object', Type::object(DummyWithNameAttributes::class)];
103104
yield ['nullable_object', Type::nullable(Type::object(DummyWithNameAttributes::class))];

src/Symfony/Component/JsonEncoder/Tests/Fixtures/decoder/iterable_dict.stream.php renamed to src/Symfony/Component/JsonEncoder/Tests/Fixtures/decoder/iterable.stream.php

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Symfony/Component/JsonEncoder/Tests/Fixtures/decoder/iterable_list.php

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/Symfony/Component/JsonEncoder/Tests/Fixtures/decoder/iterable_list.stream.php

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/Symfony/Component/JsonEncoder/Tests/Fixtures/decoder/object_iterable.php

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Symfony/Component/JsonEncoder/Tests/Fixtures/decoder/object_iterable.stream.php

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Symfony/Component/JsonEncoder/Tests/Fixtures/encoder/iterable_list.php

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/Symfony/Component/JsonEncoder/Tests/Fixtures/encoder/object_iterable.php

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Symfony/Component/JsonEncoder/Tests/JsonDecoderTest.php

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,29 @@ public function testDecodeCollection()
6464
{
6565
$decoder = JsonDecoder::create(decodersDir: $this->decodersDir, lazyGhostsDir: $this->lazyGhostsDir);
6666

67-
$this->assertDecoded($decoder, [['foo' => 1, 'bar' => 2], ['foo' => 3]], '[{"foo": 1, "bar": 2}, {"foo": 3}]', Type::list(Type::dict(Type::int())));
67+
$this->assertDecoded(
68+
$decoder,
69+
[true, false],
70+
'{"0": true, "1": false}',
71+
Type::array(Type::bool()),
72+
);
73+
74+
$this->assertDecoded(
75+
$decoder,
76+
[true, false],
77+
'[true, false]',
78+
Type::list(Type::bool()),
79+
);
80+
6881
$this->assertDecoded($decoder, function (mixed $decoded) {
6982
$this->assertIsIterable($decoded);
70-
$array = [];
71-
foreach ($decoded as $item) {
72-
$array[] = iterator_to_array($item);
73-
}
83+
$this->assertSame([true, false], iterator_to_array($decoded));
84+
}, '{"0": true, "1": false}', Type::iterable(Type::bool()));
7485

75-
$this->assertSame([['foo' => 1, 'bar' => 2], ['foo' => 3]], $array);
76-
}, '[{"foo": 1, "bar": 2}, {"foo": 3}]', Type::iterable(Type::iterable(Type::int()), Type::int(), asList: true));
86+
$this->assertDecoded($decoder, function (mixed $decoded) {
87+
$this->assertIsIterable($decoded);
88+
$this->assertSame([true, false], iterator_to_array($decoded));
89+
}, '{"0": true, "1": false}', Type::iterable(Type::bool(), Type::int()));
7790
}
7891

7992
public function testDecodeObject()

src/Symfony/Component/JsonEncoder/Tests/JsonEncoderTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,33 @@ public function testEncodeUnion()
8181
$this->assertEncoded('{"value":null}', $dummy, Type::object(DummyWithUnionProperties::class));
8282
}
8383

84+
public function testEncodeCollection()
85+
{
86+
$this->assertEncoded(
87+
'{"0":{"id":1,"name":"dummy"},"1":{"id":1,"name":"dummy"}}',
88+
[new ClassicDummy(), new ClassicDummy()],
89+
Type::array(Type::object(ClassicDummy::class)),
90+
);
91+
92+
$this->assertEncoded(
93+
'[{"id":1,"name":"dummy"},{"id":1,"name":"dummy"}]',
94+
[new ClassicDummy(), new ClassicDummy()],
95+
Type::list(Type::object(ClassicDummy::class)),
96+
);
97+
98+
$this->assertEncoded(
99+
'{"0":{"id":1,"name":"dummy"},"1":{"id":1,"name":"dummy"}}',
100+
new \ArrayObject([new ClassicDummy(), new ClassicDummy()]),
101+
Type::iterable(Type::object(ClassicDummy::class)),
102+
);
103+
104+
$this->assertEncoded(
105+
'{"0":{"id":1,"name":"dummy"},"1":{"id":1,"name":"dummy"}}',
106+
new \ArrayObject([new ClassicDummy(), new ClassicDummy()]),
107+
Type::iterable(Type::object(ClassicDummy::class), Type::int()),
108+
);
109+
}
110+
84111
public function testEncodeObject()
85112
{
86113
$dummy = new ClassicDummy();

0 commit comments

Comments
 (0)
0