Skip to content

Commit 9175fd2

Browse files
committed
Deprecate duplicate mapping keys containing null
1 parent 4c5e237 commit 9175fd2

File tree

4 files changed

+31
-6
lines changed

4 files changed

+31
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ CHANGELOG
44
7.2
55
---
66

7-
* Duplicate mapping keys throw a `ParseException` even when such key is `null`
7+
* Deprecate parsing duplicate mapping keys whose value is `null`
88

99
7.1
1010
---

Parser.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,11 @@ private function doParse(string $value, int $flags): mixed
299299
if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) {
300300
// Spec: Keys MUST be unique; first one wins.
301301
// But overwriting is allowed when a merge node is used in current block.
302-
if ($allowOverwrite || !\array_key_exists($key, $data)) {
302+
if ($allowOverwrite || !isset($data[$key])) {
303+
if (!$allowOverwrite && array_key_exists($key, $data)) {
304+
trigger_deprecation('symfony/yaml', '7.2', 'Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated and will throw a ParseException in 8.0.', $key, $this->getRealCurrentLineNb() + 1);
305+
}
306+
303307
if (null !== $subTag) {
304308
$data[$key] = new TaggedValue($subTag, '');
305309
} else {
@@ -320,7 +324,11 @@ private function doParse(string $value, int $flags): mixed
320324
}
321325

322326
$data += $value;
323-
} elseif ($allowOverwrite || !\array_key_exists($key, $data)) {
327+
} elseif ($allowOverwrite || !isset($data[$key])) {
328+
if (!$allowOverwrite && array_key_exists($key, $data)) {
329+
trigger_deprecation('symfony/yaml', '7.2', 'Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated and will throw a ParseException in 8.0.', $key, $this->getRealCurrentLineNb() + 1);
330+
}
331+
324332
// Spec: Keys MUST be unique; first one wins.
325333
// But overwriting is allowed when a merge node is used in current block.
326334
if (null !== $subTag) {
@@ -336,7 +344,11 @@ private function doParse(string $value, int $flags): mixed
336344
$value = $this->parseValue(rtrim($values['value']), $flags, $context);
337345
// Spec: Keys MUST be unique; first one wins.
338346
// But overwriting is allowed when a merge node is used in current block.
339-
if ($allowOverwrite || !\array_key_exists($key, $data)) {
347+
if ($allowOverwrite || !isset($data[$key])) {
348+
if (!$allowOverwrite && array_key_exists($key, $data)) {
349+
trigger_deprecation('symfony/yaml', '7.2', 'Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated and will throw a ParseException in 8.0.', $key, $this->getRealCurrentLineNb() + 1);
350+
}
351+
340352
$data[$key] = $value;
341353
} else {
342354
throw new ParseException(\sprintf('Duplicate key "%s" detected.', $key), $this->getRealCurrentLineNb() + 1, $this->currentLine);

Tests/ParserTest.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@
1212
namespace Symfony\Component\Yaml\Tests;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait;
1516
use Symfony\Component\Yaml\Exception\ParseException;
1617
use Symfony\Component\Yaml\Parser;
1718
use Symfony\Component\Yaml\Tag\TaggedValue;
1819
use Symfony\Component\Yaml\Yaml;
1920

2021
class ParserTest extends TestCase
2122
{
23+
use ExpectDeprecationTrait;
24+
2225
private ?Parser $parser;
2326

2427
protected function setUp(): void
@@ -1026,15 +1029,24 @@ public static function getParseExceptionOnDuplicateData()
10261029
EOD;
10271030
$tests[] = [$yaml, 'child_sequence', 6];
10281031

1032+
return $tests;
1033+
}
1034+
1035+
/**
1036+
* @group legacy
1037+
*/
1038+
public function testNullAsDuplicatedData()
1039+
{
1040+
$this->expectDeprecation('Since symfony/yaml 7.2: Duplicate key "child" detected on line 4 whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated and will throw a ParseException in 8.0.');
1041+
10291042
$yaml = <<<EOD
10301043
parent:
10311044
child:
10321045
child2:
10331046
child:
10341047
EOD;
1035-
$tests[] = [$yaml, 'child', 4];
10361048

1037-
return $tests;
1049+
Yaml::parse($yaml);
10381050
}
10391051

10401052
public function testEmptyValue()

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
],
1818
"require": {
1919
"php": ">=8.2",
20+
"symfony/deprecation-contracts": "^2.5|^3.0",
2021
"symfony/polyfill-ctype": "^1.8"
2122
},
2223
"require-dev": {

0 commit comments

Comments
 (0)