From b0a46c80cf3dbd97205f2e2ffeb9229080899c76 Mon Sep 17 00:00:00 2001 From: Johannes Schmitt Date: Sat, 21 May 2016 14:25:17 +0200 Subject: [PATCH] makes sure that explicit lists are serialized as lists If you want to make sure something is formatted as a list, i.e. ``[1, 2, 3]`` in JSON, make sure to add an explicit type like ``@Type("array")``. closes #571 closes #572 closes #488 closes #304 ...and probably more --- .../GenericSerializationVisitor.php | 8 +++++++- .../Serializer/YamlSerializationVisitor.php | 3 ++- .../Fixtures/ObjectWithIntListAndIntMap.php | 20 +++++++++++++++++++ .../Serializer/BaseSerializationTest.php | 8 ++++++++ .../Serializer/JsonSerializationTest.php | 1 + .../xml/array_list_and_map_difference.xml | 13 ++++++++++++ .../yml/array_list_and_map_difference.yml | 8 ++++++++ 7 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 tests/JMS/Serializer/Tests/Fixtures/ObjectWithIntListAndIntMap.php create mode 100644 tests/JMS/Serializer/Tests/Serializer/xml/array_list_and_map_difference.xml create mode 100644 tests/JMS/Serializer/Tests/Serializer/yml/array_list_and_map_difference.yml diff --git a/src/JMS/Serializer/GenericSerializationVisitor.php b/src/JMS/Serializer/GenericSerializationVisitor.php index a704d23bc..9f5b8be2a 100644 --- a/src/JMS/Serializer/GenericSerializationVisitor.php +++ b/src/JMS/Serializer/GenericSerializationVisitor.php @@ -98,6 +98,8 @@ public function visitArray($data, array $type, Context $context) $rs = array(); } + $isList = isset($type['params'][0]) && ! isset($type['params'][1]); + foreach ($data as $k => $v) { $v = $this->navigator->accept($v, $this->getElementType($type), $context); @@ -105,7 +107,11 @@ public function visitArray($data, array $type, Context $context) continue; } - $rs[$k] = $v; + if ($isList) { + $rs[] = $v; + } else { + $rs[$k] = $v; + } } return $rs; diff --git a/src/JMS/Serializer/YamlSerializationVisitor.php b/src/JMS/Serializer/YamlSerializationVisitor.php index d55ee7f1a..cea61facf 100644 --- a/src/JMS/Serializer/YamlSerializationVisitor.php +++ b/src/JMS/Serializer/YamlSerializationVisitor.php @@ -81,7 +81,8 @@ public function visitString($data, array $type, Context $context) public function visitArray($data, array $type, Context $context) { $count = $this->writer->changeCount; - $isList = array_keys($data) === range(0, count($data) - 1); + $isList = (isset($type['params'][0]) && ! isset($type['params'][1])) + || array_keys($data) === range(0, count($data) - 1); foreach ($data as $k => $v) { if (null === $v && ( ! is_string($k) || ! $context->shouldSerializeNull())) { diff --git a/tests/JMS/Serializer/Tests/Fixtures/ObjectWithIntListAndIntMap.php b/tests/JMS/Serializer/Tests/Fixtures/ObjectWithIntListAndIntMap.php new file mode 100644 index 000000000..f5f1e8da8 --- /dev/null +++ b/tests/JMS/Serializer/Tests/Fixtures/ObjectWithIntListAndIntMap.php @@ -0,0 +1,20 @@ +") @Serializer\XmlList */ + private $list; + + /** @Serializer\Type("array") @Serializer\XmlMap */ + private $map; + + public function __construct(array $list, array $map) + { + $this->list = $list; + $this->map = $map; + } +} \ No newline at end of file diff --git a/tests/JMS/Serializer/Tests/Serializer/BaseSerializationTest.php b/tests/JMS/Serializer/Tests/Serializer/BaseSerializationTest.php index 670e5fa20..8cd156644 100644 --- a/tests/JMS/Serializer/Tests/Serializer/BaseSerializationTest.php +++ b/tests/JMS/Serializer/Tests/Serializer/BaseSerializationTest.php @@ -29,6 +29,7 @@ use JMS\Serializer\Tests\Fixtures\Garage; use JMS\Serializer\Tests\Fixtures\InlineChildEmpty; use JMS\Serializer\Tests\Fixtures\NamedDateTimeArraysObject; +use JMS\Serializer\Tests\Fixtures\ObjectWithIntListAndIntMap; use JMS\Serializer\Tests\Fixtures\Tag; use JMS\Serializer\Tests\Fixtures\Timestamp; use JMS\Serializer\Tests\Fixtures\Tree; @@ -277,6 +278,13 @@ public function testArrayObjects() } } + public function testArrayListAndMapDifference() + { + $arrayData = array(0 => 1, 2 => 2, 3 => 3); // Misses key 1 + $data = new ObjectWithIntListAndIntMap($arrayData, $arrayData); + + $this->assertEquals($this->getContent('array_list_and_map_difference'), $this->serialize($data)); + } public function testDateTimeArrays() { diff --git a/tests/JMS/Serializer/Tests/Serializer/JsonSerializationTest.php b/tests/JMS/Serializer/Tests/Serializer/JsonSerializationTest.php index 91b46e88e..75062e381 100644 --- a/tests/JMS/Serializer/Tests/Serializer/JsonSerializationTest.php +++ b/tests/JMS/Serializer/Tests/Serializer/JsonSerializationTest.php @@ -49,6 +49,7 @@ protected function getContent($key) $outputs['array_empty'] = '{"array":[]}'; $outputs['array_floats'] = '[1.34,3,6.42]'; $outputs['array_objects'] = '[{"foo":"foo","moo":"bar","camel_case":"boo"},{"foo":"baz","moo":"boo","camel_case":"boo"}]'; + $outputs['array_list_and_map_difference'] = '{"list":[1,2,3],"map":{"0":1,"2":2,"3":3}}'; $outputs['array_mixed'] = '["foo",1,true,{"foo":"foo","moo":"bar","camel_case":"boo"},[1,3,true]]'; $outputs['array_datetimes_object'] = '{"array_with_default_date_time":["2047-01-01T12:47:47+0000","2013-12-05T00:00:00+0000"],"array_with_formatted_date_time":["01.01.2047 12:47:47","05.12.2013 00:00:00"]}'; $outputs['array_named_datetimes_object'] = '{"named_array_with_formatted_date":{"testdate1":"01.01.2047 12:47:47","testdate2":"05.12.2013 00:00:00"}}'; diff --git a/tests/JMS/Serializer/Tests/Serializer/xml/array_list_and_map_difference.xml b/tests/JMS/Serializer/Tests/Serializer/xml/array_list_and_map_difference.xml new file mode 100644 index 000000000..557b0ad0a --- /dev/null +++ b/tests/JMS/Serializer/Tests/Serializer/xml/array_list_and_map_difference.xml @@ -0,0 +1,13 @@ + + + + 1 + 2 + 3 + + + 1 + 2 + 3 + + diff --git a/tests/JMS/Serializer/Tests/Serializer/yml/array_list_and_map_difference.yml b/tests/JMS/Serializer/Tests/Serializer/yml/array_list_and_map_difference.yml new file mode 100644 index 000000000..05d6fde21 --- /dev/null +++ b/tests/JMS/Serializer/Tests/Serializer/yml/array_list_and_map_difference.yml @@ -0,0 +1,8 @@ +list: + - 1 + - 2 + - 3 +map: + 0: 1 + 2: 2 + 3: 3