Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

js-yaml issue with tags

Tags:

node.js

yaml

I am currently trying to edit 2 messages in a yaml file but js-yaml does not seem to understand what to do with what I think is a tag on the first line:

--- !Status
Default:
    Description:
        - |-
            Message1
            Message2
Samples:
    Multiple: false
    DynamicPlayers: false
Unknown:
    PlayerName: player
    PlayerCount: '???'
Favicon:
    Timeout: 10s
    RecursiveFolderSearch: false
    ResizeStrategy: SCALE

When I safeload the document I get: YAMLException: unknown tag !<!Status> at line 17, column 1: Is there any way for me to just let it ignore the tag or is there a different way around this problem? I'm not able to remove the tag because that would stop the program from reading the config file.

like image 952
Dwayne Hulsman Avatar asked Dec 18 '22 11:12

Dwayne Hulsman


2 Answers

Take a look at examples/custom_types.js in the js-yaml repo. The solution is to create a new jsyaml.Type that tells js-yaml to treat !Status values as mappings, like so:

let StatusYamlType = new jsyaml.Type('!Status', { kind: 'mapping' });

Then you need to create a new Schema that includes the StatusYamlType type:

let STATUS_SCHEMA = jsyaml.Schema.create([ StatusYamlType ]);

Finally, pass the new STATUS_SCHEMA to jsyaml.safeLoad via the schema option:

jsyaml.safeLoad(doc, { schema: STATUS_SCHEMA });

Unfortunately, it doesn't look like there's a way to make js-yaml ignore all tags, so if you encounter others you'll have to define Types for them as well.

If you also want to write YAML files with the !Status tag then you'll have to actually define a Status prototype and supply the construct and instanceOf options to the jsyaml.Type constructor as in the example. A very basic implementation looks like this:

function Status(data) {
  Object.assign(this, data);
}

let StatusYamlType = new jsyaml.Type('!Status', {
  kind: 'mapping',
  instanceOf: Status,
  construct: data => new Status(data),
});

Then you pass the schema to jsyaml.safeDump just like you did to safeLoad:

jsyaml.safeDump(result, { schema: STATUS_SCHEMA })

Take a look at the below snippet to see it in action.

let doc = `--- !Status
Default:
    Description:
        - |-
            Message1
            Message2
# ...
`;

function Status(data) {
  Object.assign(this, data);
}

let StatusYamlType = new jsyaml.Type('!Status', {
  kind: 'mapping',
  instanceOf: Status,
  construct: data => new Status(data),
});

let STATUS_SCHEMA = jsyaml.Schema.create([ StatusYamlType ]);

let result = jsyaml.safeLoad(doc, { schema: STATUS_SCHEMA });
console.log(result.constructor.name, result);

console.log(jsyaml.safeDump(result, { schema: STATUS_SCHEMA }));
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-yaml/3.7.0/js-yaml.min.js"></script>

As you can see, the safeDump output uses a slightly different tag syntax than your original input (!<!Status> rather than --- !Status), but in this context they are equivalent and YAML parsers should treat them as such.

like image 90
Jordan Running Avatar answered Jan 13 '23 23:01

Jordan Running


I had the same issue with an AWS Cloud Formation Template when editing it in Visual Studio Code.

I found that within the user settings if I added the following lines of code to my user-settings.json, it allowed for the tags.

    "yaml.customTags": [
        "!Equals sequence",
        "!FindInMap sequence",
        "!GetAtt",
        "!GetAZs",
        "!ImportValue",
        "!Join sequence",
        "!Ref",
        "!Select sequence",
        "!Split sequence",
        "!Sub"
    ]

Yours would follow the same contruct. "!Status sequence"

This tells the YAML configuration exactly what to expect.

like image 29
Justin Rice Avatar answered Jan 14 '23 00:01

Justin Rice