Add Yaml::PARSE_EXCEPTION_ON_DUPLICATE to throw exceptions on duplicates

This commit is contained in:
Alex Pott 2016-08-04 13:37:15 +01:00 committed by Fabien Potencier
parent e408b50c5a
commit cb362f284f
8 changed files with 99 additions and 5 deletions

View File

@ -70,3 +70,9 @@ Validator
// ...
}
```
Yaml
----
* Support for silently ignoring duplicate keys in YAML has been deprecated and
will lead to a `ParseException` in Symfony 4.0.

View File

@ -230,6 +230,9 @@ Yaml
* The `!!php/object` tag to indicate dumped PHP objects was removed in favor of
the `!php/object` tag.
* Duplicate keys in YAML leads to a `ParseException`.
Validator
---------

View File

@ -10,6 +10,9 @@ CHANGELOG
Yaml::parse('!php/const:PHP_INT_MAX', Yaml::PARSE_CONSTANT);
```
* Support for silently ignoring duplicate keys in YAML has been deprecated and
will lead to a `ParseException` in Symfony 4.0.
3.1.0
-----

View File

@ -475,6 +475,8 @@ class Inline
// are processed sequentially.
if (!isset($output[$key])) {
$output[$key] = $value;
} else {
@trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED);
}
$done = true;
break;
@ -486,6 +488,8 @@ class Inline
// are processed sequentially.
if (!isset($output[$key])) {
$output[$key] = $value;
} else {
@trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED);
}
$done = true;
break;
@ -499,6 +503,8 @@ class Inline
// are processed sequentially.
if (!isset($output[$key])) {
$output[$key] = $value;
} else {
@trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED);
}
$done = true;
--$i;

View File

@ -241,6 +241,8 @@ class Parser
// But overwriting is allowed when a merge node is used in current block.
if ($allowOverwrite || !isset($data[$key])) {
$data[$key] = null;
} else {
@trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED);
}
} else {
$value = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(), $flags);
@ -248,6 +250,8 @@ class Parser
// But overwriting is allowed when a merge node is used in current block.
if ($allowOverwrite || !isset($data[$key])) {
$data[$key] = $value;
} else {
@trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED);
}
}
} else {
@ -256,6 +260,8 @@ class Parser
// But overwriting is allowed when a merge node is used in current block.
if ($allowOverwrite || !isset($data[$key])) {
$data[$key] = $value;
} else {
@trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED);
}
}
if ($isRef) {

View File

@ -1574,6 +1574,7 @@ php: |
array(
'fixed' => 1230.15,
)
---
test: Float
yaml: |
canonical: 1.23015e+3

View File

@ -18,11 +18,7 @@ yaml: |
x: Oren
c:
foo: bar
foo: ignore
bar: foo
duplicate:
foo: bar
foo: ignore
foo2: &foo2
a: Ballmer
ding: &dong [ fi, fei, fo, fam]
@ -48,7 +44,6 @@ php: |
array(
'foo' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian'),
'bar' => array('a' => 'before', 'd' => 'other', 'b' => 'new', 'c' => array('foo' => 'bar', 'bar' => 'foo'), 'x' => 'Oren'),
'duplicate' => array('foo' => 'bar'),
'foo2' => array('a' => 'Ballmer'),
'ding' => array('fi', 'fei', 'fo', 'fam'),
'check' => array('a' => 'Steve', 'b' => 'Clark', 'c' => 'Brian', 'fi', 'fei', 'fo', 'fam', 'isit' => 'tested'),

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Yaml\Tests;
use Symfony\Bridge\PhpUnit\ErrorAssert;
use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Yaml\Parser;
@ -770,6 +771,7 @@ EOF
*
* @see http://yaml.org/spec/1.2/spec.html#id2759572
* @see http://yaml.org/spec/1.1/#id932806
* @group legacy
*/
public function testMappingDuplicateKeyBlock()
{
@ -789,6 +791,9 @@ EOD;
$this->assertSame($expected, Yaml::parse($input));
}
/**
* @group legacy
*/
public function testMappingDuplicateKeyFlow()
{
$input = <<<EOD
@ -803,6 +808,75 @@ EOD;
$this->assertSame($expected, Yaml::parse($input));
}
/**
* @dataProvider getParseExceptionOnDuplicateData
* @requires function Symfony\Bridge\PhpUnit\ErrorAssert::assertDeprecationsAreTriggered
* throws \Symfony\Component\Yaml\Exception\ParseException in 4.0
*/
public function testParseExceptionOnDuplicate($input, $duplicate_key)
{
ErrorAssert::assertDeprecationsAreTriggered(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $duplicate_key), function () use ($input) {
Yaml::parse($input);
});
}
public function getParseExceptionOnDuplicateData()
{
$tests = array();
$yaml = <<<EOD
parent: { child: first, child: duplicate }
EOD;
$tests[] = array($yaml, 'child');
$yaml = <<<EOD
parent:
child: first,
child: duplicate
EOD;
$tests[] = array($yaml, 'child');
$yaml = <<<EOD
parent: { child: foo }
parent: { child: bar }
EOD;
$tests[] = array($yaml, 'parent');
$yaml = <<<EOD
parent: { child_mapping: { value: bar}, child_mapping: { value: bar} }
EOD;
$tests[] = array($yaml, 'child_mapping');
$yaml = <<<EOD
parent:
child_mapping:
value: bar
child_mapping:
value: bar
EOD;
$tests[] = array($yaml, 'child_mapping');
$yaml = <<<EOD
parent: { child_sequence: ['key1', 'key2', 'key3'], child_sequence: ['key1', 'key2', 'key3'] }
EOD;
$tests[] = array($yaml, 'child_sequence');
$yaml = <<<EOD
parent:
child_sequence:
- key1
- key2
- key3
child_sequence:
- key1
- key2
- key3
EOD;
$tests[] = array($yaml, 'child_sequence');
return $tests;
}
public function testEmptyValue()
{
$input = <<<'EOF'