0

I'm using SnakeYaml and Java to try and write to a yaml file, but I'm seeing weird characters during dumping...

Here is what I have:

PrintWriter writer = new PrintWriter(new File("./output.yaml"));

DumperOptions mapOptions = new DumperOptions();
mapOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.AUTO);
mapOptions.setDefaultScalarStyle(DumperOptions.ScalarStyle.LITERAL); // THIS LINE
mapOptions.setPrettyFlow(true);

Yaml mapYaml = new Yaml(mapOptions);

mapYaml.dump("mapping:", writer);
mapYaml.dump("  \"table\":" + "\"" + map.get(tableName) + "\"", writer);

What I'm expecting :

mapping:
  "table": "tableName"

What I'm getting as output:

|- 
  mapping:
|2- 
    "table": "tableName"

I also tried without the DumperOptions.ScalarStyle.Literal line (// THIS LINE comment), but I was getting this instead:

'mapping:'
'  "table": "tableName"'

For either method, how can I

(1) Clean up the |- and |2- symbols from being dumped? (with ScalarStyle.LITERAL)

or

(2) Clean up the single quotes from being printed? (without ScalarStyle.LITERAL)

I appreciate any guidance anyone can give me about this..

Thank you ahead of time!

wood
  • 21
  • 1

1 Answers1

0

You are using the YAML dumper as if it was a simple output stream. What do you think the YAML dumper does? If it would just write out the strings you give it, there would be no point using it.

Now let's see what's actually happening:

mapYaml.dump("mapping:", writer);

Here you are asking the YAML dumper to dump a single string, mapping:. If you give DumperOptions.ScalarStyle.LITERAL, the YAML dumper will do exactly what you ask of it and dump it as literal block scalar:

|- 
  mapping:

The character | starts a literal block scalar. All following lines that are more indented will be read literally without any processing. This will make this YAML load as the string mapping:, just as you requested. The - behind the | tells the literal block scalar to not include the final line break in the value.

If you leave out DumperOptions.ScalarStyle.LITERAL, the YAML dumper needs to accommodate for the fact that the colon in YAML is a special character. Since you explicitly ask the dumper for it to be part of a string, the dumper needs to quote that string:

'mapping:'

The YAML document you just saw is complete. Every call to dump emits a complete YAML document and you cannot just concatenate them and expect them to merge together into a single YAML document. So calling dump two times is not what you actually want.

Now let's discuss the second line:

mapYaml.dump("  \"table\":" + "\"" + map.get(tableName) + "\"", writer);

What happens in the output is mostly the same as in the first case. The 2 in the literal block scalar indicates that exactly two spaces are read as indentation. This causes the additional two space at the beginning to be read as content, just as you requested. Without DumperOptions.ScalarStyle.LITERAL, the dumper again needs to quote the string because it contains spaces, double quotes, and a colon, all of which are special YAML characters.

Evidently, none of this is what you want to do. You need to understand that the YAML dumper takes a data structure and serializes it as YAML. So what you need to do is to give it the data structure you want:

mapYaml.dump(Map.of("mapping", Map.of("table", map.get(tableName)));

Also replace DumperOptions.ScalarStyle.LITERAL with DumperOptions.FlowStyle.BLOCK. This will give you the structure you want, albeit without the double quotes. This does not matter since the resulting YAML is equivalent.

For forcing these scalars to be quoted, see this answer.

flyx
  • 35,506
  • 7
  • 89
  • 126