Skip to content

@std/yaml: stringify() with condenseFlow wraps already quoted keys in a second pair of quotes #7362

Open

Description

@auraseb

What happens

With condenseFlow: true, stringify() wraps every flow mapping key in double quotes, even when the key was already emitted as a quoted scalar. Keys that need quoting (numeric strings, true, #, the empty string, strings with " or a newline) come out double wrapped. Parsing the output either returns a different key or throws.

import { parse, stringify } from "jsr:@std/yaml";

const options = { flowLevel: 0, condenseFlow: true };

stringify({ "1": 1 }, options);    // {"'1'":1}    parses back as { "'1'": 1 }
stringify({ "": 1 }, options);     // {"''":1}     parses back as { "''": 1 }
stringify({ 'a"b': 1 }, options);  // {"a"b":1}    parse() throws
stringify({ "a\nb": 1 }, options); // {""a\nb"":1} parse() throws
stringify({ "a\\nb": 1 }, options); // {"a\nb":1}  parses back with a real newline

Keys longer than 1024 characters also get the ? explicit key marker inside the quotes, so the parsed key starts with ? .

What should happen

The output should be valid YAML that parses back to the same object, for example {'1':1} and {"a\"b":1}.

Root cause

DumperState.stringifyFlowMapping() in yaml/_dumper_state.ts builds each pair as quote + keyPrefix + keyString + quote, where keyString is the already serialized key and may already be quoted. Plain keys are also wrapped without escaping, so a plain key containing \ or " changes meaning inside the double quotes.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions