Search code examples
javayamlsnakeyaml

How to parse YAML file to Nodes in SnakeYAML-engine


Problem

I need to parse YAML files in a Java codebase but not only that: I need to know for my application the line numbers of the parsed keys. I'd want to parse YAML files using the 1.2 specification. Right now I'm using SnakeYAML engine but I'm open to any other library.

My research so far

I am attempting to use SnakeYAML engine since it parses yaml files using 1.2 specification instead of 1.1 like for SnakeYAML.

For SnakeYAML I found this conversation which includes an useful code snippet:

Node node = yaml.compose(new InputStreamReader(yamlStream));

This Node class is what I need. It contains the lines where each keyword was found in the file, but the snippet is relative only to SnakeYAML and not SnakeYAML engine.

I'd need an equivalent line (or block of lines) of code to achieve the same thing. I can see in the SnakeYAML engine there is an equivalent Node (org.snakeyaml.engine.v2.nodes.Node) class which I can read from the class comments:

[...] the node graph is usually created by the org.snakeyaml.engine.v2.composer.Composer    

In the SnakeYAML engine documentation I do not see anything useful to me and I can't find resources online. Any help?

Application details

I am using java 11 and the classes previously mentioned are from SnakeYAML engine version 2.0, although I am free to use other versions if needed.

Some code if you need

Inside build.gradle:

//implementation 'org.yaml:snakeyaml:1.27', if you want to test it
implementation 'org.snakeyaml:snakeyaml-engine:2.0'

Inside Main.java main method:

//code for SnakeYAML
Node node = new org.yaml.snakeyaml.Yaml().compose(new StringReader("key: value"));

Solution

  • I think you're looking for Compose. It can be constructed and used quite easily:

    LoadSettings settings = LoadSettings.builder()
            .setUseMarks(true)
            // other settings as needed
            .build();
    Compose compose = new Compose(settings);
    Node node = compose.composeInputStream(yamlStream).orElseThrow();
    // without the setUseMarks(true), these two will fail
    Mark startMark = node.getStartMark().orElseThrow();
    Mark endMark = node.getEndMark().orElseThrow();