i am trying to read a Yaml template and replace certain fields in the template dynamically and create a new Yaml file. My resultant yaml file should reflect the template in all aspects including the double quotes. But I am missing double quotes for the required fields when I use snake yaml. Can anyone please suggest to resolve this issue?
Example :
My yaml template is as shown below:
version: snapshot-01 kind: sample metadata: name: abc groups: id: "1000B" category: category1
I am reading the above template and replacing the required fields dynamically as shown below.
Yaml yaml = new Yaml(); InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(yamlTemplateLocation); Map<String, Object>yamlMap = yaml.load(inputStream);
Now I am replacing the required fields as shown below
yamlMap.put("version","v-1.0"); Map<String, Object> metadata = (Map<String, Object>) yamlMap.get("metadata"); metadata.put("name", "XYZ"); Map<String, Object> groups = (Map<String, Object>) yamlMap.get("groups"); groups.put("id","5000Z"); groups.put("category","newCategory"); DumperOptions options = new DumperOptions(); options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); options.setPrettyFlow(true); Yaml yaml = new Yaml(options); String output = yaml.dump(map); System.out.println(output);
I am expecting output as shown below
Expected Output :
version: v-1.0 kind: sample metadata: name: XYZ groups: id: "5000Z" category: newCategory
But I am actually getting output as below
version: v-1.0 kind: sample metadata: name: XYZ groups: id: 5000Z category: newCategory
My problem here is, I am missing the double quotes for “id” node in the new yaml file. When I use, options.setDefaultScalarStyle(ScalarStyle.DOUBLE_QUOTED), I am getting all fields double quoted which is not required. I need double quotes for id field only. Can anyone please advice to resolve this issue.
Thanks
Advertisement
Answer
If your input is a template, it might be better to use a templating engine. As simple example, MessageFormat
would allow you to write id: "{0}"
and then interpolate the actual value into it, keeping the double quotes. You could use more sophisticated templating depending on your use-case.
That being said, let’s look at how to do it with SnakeYAML:
If you want to control how a single item is rendered as scalar, you have to define a class like this:
class QuotedString { public String value; public QuotedString(String value) { this.value = value; } }
And then create a custom representer for it:
class MyRepresenter extends Representer { public MyRepresenter() { this.representers.put(QuotedString.class, new RepresentQuotedString()); } private class RepresentQuotedString implements Represent { public Node representData(Object data) { QuotedString str = (QuotedString) data; return representScalar( Tag.STR, str.value, DumperOptions.ScalarStyle.DOUBLE_QUOTED); } } }
Modify your code to use the new class:
groups.put("id", new QuotedString("5000Z"));
And finally, instruct SnakeYAML to use your representer:
Yaml yaml = new Yaml(new MyRepresenter(), options);
This should do it.