Skip to content

Commit 871f18d

Browse files
committed
[Yaml] properly parse lists in object maps
* do not cast parsed sequences to objects * properly handle numeric mapping keys
1 parent 33fd1b2 commit 871f18d

File tree

2 files changed

+66
-20
lines changed

2 files changed

+66
-20
lines changed

Parser.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,14 @@ public function parse($value, $exceptionOnInvalidType = false, $objectSupport =
303303
mb_internal_encoding($mbEncoding);
304304
}
305305

306-
if ($objectForMap && !is_object($data)) {
307-
$data = (object) $data;
306+
if ($objectForMap && !is_object($data) && 'mapping' === $context) {
307+
$object = new \stdClass();
308+
309+
foreach ($data as $key => $value) {
310+
$object->$key = $value;
311+
}
312+
313+
$data = $object;
308314
}
309315

310316
return empty($data) ? null : $data;

Tests/ParserTest.php

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -442,35 +442,75 @@ public function testObjectSupportDisabledButNoExceptions($input)
442442
$this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects');
443443
}
444444

445-
public function testObjectForMapEnabledWithMapping()
445+
/**
446+
* @dataProvider getObjectForMapTests
447+
*/
448+
public function testObjectForMap($yaml, $expected)
449+
{
450+
$this->assertEquals($expected, $this->parser->parse($yaml, false, false, true));
451+
}
452+
453+
public function getObjectForMapTests()
446454
{
455+
$tests = array();
456+
447457
$yaml = <<<EOF
448458
foo:
449459
fiz: [cat]
450460
EOF;
451-
$result = $this->parser->parse($yaml, false, false, true);
452-
453-
$this->assertInstanceOf('stdClass', $result);
454-
$this->assertInstanceOf('stdClass', $result->foo);
455-
$this->assertEquals(array('cat'), $result->foo->fiz);
456-
}
457-
458-
public function testObjectForMapEnabledWithInlineMapping()
459-
{
460-
$result = $this->parser->parse('{ "foo": "bar", "fiz": "cat" }', false, false, true);
461+
$expected = new \stdClass();
462+
$expected->foo = new \stdClass();
463+
$expected->foo->fiz = array('cat');
464+
$tests['mapping'] = array($yaml, $expected);
461465

462-
$this->assertInstanceOf('stdClass', $result);
463-
$this->assertEquals('bar', $result->foo);
464-
$this->assertEquals('cat', $result->fiz);
465-
}
466+
$yaml = '{ "foo": "bar", "fiz": "cat" }';
467+
$expected = new \stdClass();
468+
$expected->foo = 'bar';
469+
$expected->fiz = 'cat';
470+
$tests['inline-mapping'] = array($yaml, $expected);
466471

467-
public function testObjectForMapIsAppliedAfterParsing()
468-
{
472+
$yaml = "foo: bar\nbaz: foobar";
469473
$expected = new \stdClass();
470474
$expected->foo = 'bar';
471475
$expected->baz = 'foobar';
476+
$tests['object-for-map-is-applied-after-parsing'] = array($yaml, $expected);
472477

473-
$this->assertEquals($expected, $this->parser->parse("foo: bar\nbaz: foobar", false, false, true));
478+
$yaml = <<<EOT
479+
array:
480+
- key: one
481+
- key: two
482+
EOT;
483+
$expected = new \stdClass();
484+
$expected->array = array();
485+
$expected->array[0] = new \stdClass();
486+
$expected->array[0]->key = 'one';
487+
$expected->array[1] = new \stdClass();
488+
$expected->array[1]->key = 'two';
489+
$tests['nest-map-and-sequence'] = array($yaml, $expected);
490+
491+
$yaml = <<<YAML
492+
map:
493+
1: one
494+
2: two
495+
YAML;
496+
$expected = new \stdClass();
497+
$expected->map = new \stdClass();
498+
$expected->map->{1} = 'one';
499+
$expected->map->{2} = 'two';
500+
$tests['numeric-keys'] = array($yaml, $expected);
501+
502+
$yaml = <<<YAML
503+
map:
504+
0: one
505+
1: two
506+
YAML;
507+
$expected = new \stdClass();
508+
$expected->map = new \stdClass();
509+
$expected->map->{0} = 'one';
510+
$expected->map->{1} = 'two';
511+
$tests['zero-indexed-numeric-keys'] = array($yaml, $expected);
512+
513+
return $tests;
474514
}
475515

476516
/**

0 commit comments

Comments
 (0)