Skip to content

Commit

Permalink
[Yaml] Add flag to dump numeric key as string
Browse files Browse the repository at this point in the history
  • Loading branch information
alamirault authored and derrabus committed Dec 19, 2022
1 parent ea9ed6c commit 35890e1
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/Symfony/Component/Yaml/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
CHANGELOG
=========

6.3
---

* Add support to dump int keys as strings by using the `Yaml::DUMP_NUMERIC_KEY_AS_STRING` flag.

6.2
---

Expand Down
4 changes: 4 additions & 0 deletions src/Symfony/Component/Yaml/Dumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ public function dump(mixed $input, int $inline = 0, int $indent = 0, int $flags
$output .= "\n";
}

if (\is_int($key) && Yaml::DUMP_NUMERIC_KEY_AS_STRING & $flags) {
$key = (string) $key;
}

if (Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK & $flags && \is_string($value) && str_contains($value, "\n") && !str_contains($value, "\r")) {
// If the first line starts with a space character, the spec requires a blockIndicationIndicator
// http://www.yaml.org/spec/1.2/spec.html#id2793979
Expand Down
4 changes: 4 additions & 0 deletions src/Symfony/Component/Yaml/Inline.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@ private static function dumpHashArray(array|\ArrayObject|\stdClass $value, int $
{
$output = [];
foreach ($value as $key => $val) {
if (\is_int($key) && Yaml::DUMP_NUMERIC_KEY_AS_STRING & $flags) {
$key = (string) $key;
}

$output[] = sprintf('%s: %s', self::dump($key, $flags), self::dump($val, $flags));
}

Expand Down
90 changes: 90 additions & 0 deletions src/Symfony/Component/Yaml/Tests/DumperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,96 @@ public function testDumpNullAsTilde()
$this->assertSame('{ foo: ~ }', $this->dumper->dump(['foo' => null], 0, 0, Yaml::DUMP_NULL_AS_TILDE));
}

/**
* @dataProvider getNumericKeyData
*/
public function testDumpInlineNumericKeyAsString(array $input, bool $inline, int $flags, string $expected)
{
$this->assertSame($expected, $this->dumper->dump($input, $inline ? 0 : 4, 0, $flags));
}

public function getNumericKeyData()
{
yield 'Int key with flag inline' => [
[200 => 'foo'],
true,
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '200': foo }",
];

yield 'Int key without flag inline' => [
[200 => 'foo'],
true,
0,
'{ 200: foo }',
];

$expected = <<<'YAML'
'200': foo
YAML;

yield 'Int key with flag' => [
[200 => 'foo'],
false,
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
$expected,
];

$expected = <<<'YAML'
200: foo
YAML;

yield 'Int key without flag' => [
[200 => 'foo'],
false,
0,
$expected,
];

$expected = <<<'YAML'
- 200
- foo
YAML;

yield 'List array with flag' => [
[200, 'foo'],
false,
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
$expected,
];

$expected = <<<'YAML'
'200': !number 5
YAML;

yield 'Int tagged value with flag' => [
[
200 => new TaggedValue('number', 5),
],
false,
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
$expected,
];

$expected = <<<'YAML'
200: !number 5
YAML;

yield 'Int tagged value without flag' => [
[
200 => new TaggedValue('number', 5),
],
false,
0,
$expected,
];
}

public function testDumpIdeographicSpaces()
{
$expected = <<<YAML
Expand Down
92 changes: 92 additions & 0 deletions src/Symfony/Component/Yaml/Tests/InlineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,98 @@ public function testDumpDateTime($dateTime, $expected)
$this->assertSame($expected, Inline::dump($dateTime));
}

/**
* @dataProvider getNumericKeyData
*/
public function testDumpNumericKeyAsString(array|int $input, int $flags, string $expected)
{
$this->assertSame($expected, Inline::dump($input, $flags));
}

public function getNumericKeyData()
{
yield 'Int with flag' => [
200,
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
'200',
];

yield 'Int key with flag' => [
[200 => 'foo'],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '200': foo }",
];

yield 'Int value with flag' => [
[200 => 200],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '200': 200 }",
];

yield 'String key with flag' => [
['200' => 'foo'],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '200': foo }",
];

yield 'Mixed with flag' => [
[42 => 'a', 'b' => 'c', 'd' => 43],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '42': a, b: c, d: 43 }",
];

yield 'Auto-index with flag' => [
['a', 'b', 42],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
'[a, b, 42]',
];

yield 'Complex mixed array with flag' => [
[
42 => [
'foo' => 43,
44 => 'bar',
],
45 => 'baz',
46,
],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
"{ '42': { foo: 43, '44': bar }, '45': baz, '46': 46 }",
];

yield 'Int tagged value with flag' => [
[
'count' => new TaggedValue('number', 5),
],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
'{ count: !number 5 }',
];

yield 'Array tagged value with flag' => [
[
'user' => new TaggedValue('metadata', [
'john',
42,
]),
],
Yaml::DUMP_NUMERIC_KEY_AS_STRING,
'{ user: !metadata [john, 42] }',
];

$arrayObject = new \ArrayObject();
$arrayObject['foo'] = 'bar';
$arrayObject[42] = 'baz';
$arrayObject['baz'] = 43;

yield 'Object value with flag' => [
[
'user' => $arrayObject,
],
Yaml::DUMP_NUMERIC_KEY_AS_STRING | Yaml::DUMP_OBJECT_AS_MAP,
"{ user: { foo: bar, '42': baz, baz: 43 } }",
];
}

public function testDumpUnitEnum()
{
$this->assertSame("!php/const Symfony\Component\Yaml\Tests\Fixtures\FooUnitEnum::BAR", Inline::dump(FooUnitEnum::BAR));
Expand Down
1 change: 1 addition & 0 deletions src/Symfony/Component/Yaml/Yaml.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Yaml
public const PARSE_CUSTOM_TAGS = 512;
public const DUMP_EMPTY_ARRAY_AS_SEQUENCE = 1024;
public const DUMP_NULL_AS_TILDE = 2048;
public const DUMP_NUMERIC_KEY_AS_STRING = 4096;

/**
* Parses a YAML file into a PHP value.
Expand Down

0 comments on commit 35890e1

Please sign in to comment.