From ee9ca936002417bf105c4c7e88ae5be6f9083af2 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 8 Feb 2016 19:04:09 +0100 Subject: [PATCH] [Yaml] properly parse lists in object maps * do not cast parsed sequences to objects * properly handle numeric mapping keys --- src/Symfony/Component/Yaml/Parser.php | 10 ++- .../Component/Yaml/Tests/ParserTest.php | 76 ++++++++++++++----- 2 files changed, 66 insertions(+), 20 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 233a51d9cd..41134e6b6c 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -303,8 +303,14 @@ class Parser mb_internal_encoding($mbEncoding); } - if ($objectForMap && !is_object($data)) { - $data = (object) $data; + if ($objectForMap && !is_object($data) && 'mapping' === $context) { + $object = new \stdClass(); + + foreach ($data as $key => $value) { + $object->$key = $value; + } + + $data = $object; } return empty($data) ? null : $data; diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 062161836c..deb59e4240 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -442,35 +442,75 @@ EOF; $this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects'); } - public function testObjectForMapEnabledWithMapping() + /** + * @dataProvider getObjectForMapTests + */ + public function testObjectForMap($yaml, $expected) { + $this->assertEquals($expected, $this->parser->parse($yaml, false, false, true)); + } + + public function getObjectForMapTests() + { + $tests = array(); + $yaml = <<parser->parse($yaml, false, false, true); + $expected = new \stdClass(); + $expected->foo = new \stdClass(); + $expected->foo->fiz = array('cat'); + $tests['mapping'] = array($yaml, $expected); - $this->assertInstanceOf('stdClass', $result); - $this->assertInstanceOf('stdClass', $result->foo); - $this->assertEquals(array('cat'), $result->foo->fiz); - } + $yaml = '{ "foo": "bar", "fiz": "cat" }'; + $expected = new \stdClass(); + $expected->foo = 'bar'; + $expected->fiz = 'cat'; + $tests['inline-mapping'] = array($yaml, $expected); - public function testObjectForMapEnabledWithInlineMapping() - { - $result = $this->parser->parse('{ "foo": "bar", "fiz": "cat" }', false, false, true); - - $this->assertInstanceOf('stdClass', $result); - $this->assertEquals('bar', $result->foo); - $this->assertEquals('cat', $result->fiz); - } - - public function testObjectForMapIsAppliedAfterParsing() - { + $yaml = "foo: bar\nbaz: foobar"; $expected = new \stdClass(); $expected->foo = 'bar'; $expected->baz = 'foobar'; + $tests['object-for-map-is-applied-after-parsing'] = array($yaml, $expected); - $this->assertEquals($expected, $this->parser->parse("foo: bar\nbaz: foobar", false, false, true)); + $yaml = <<array = array(); + $expected->array[0] = new \stdClass(); + $expected->array[0]->key = 'one'; + $expected->array[1] = new \stdClass(); + $expected->array[1]->key = 'two'; + $tests['nest-map-and-sequence'] = array($yaml, $expected); + + $yaml = <<map = new \stdClass(); + $expected->map->{1} = 'one'; + $expected->map->{2} = 'two'; + $tests['numeric-keys'] = array($yaml, $expected); + + $yaml = <<map = new \stdClass(); + $expected->map->{0} = 'one'; + $expected->map->{1} = 'two'; + $tests['zero-indexed-numeric-keys'] = array($yaml, $expected); + + return $tests; } /**