Reputation: 59
How do you parse a YAML file containing tagged maps and return nested Java Map<String, Object> objects, where each Java Map contains all entries from the corresponding YAML map, plus an entry where the key is a the String “objectType” and the value is the (String) name of the tag?
In other words, I'd like to parse tagged YAML objects as if they were JSON objects with an entry for the type.
For example, how do you parse this:
!ControlGroup
name: myGroup
controls:
- !Button
name: button1
size: 10
- !Knob
name: knob1
maxValue: 11
size: 7
as if it were this?:
objectType: ControlGroup
name: myGroup
controls:
- objectType: Button
name: button1
size: 10
- objectType: Knob
name: knob1
maxValue: 11
size: 7
I'm already using SnakeYAML in the project I'm working on, so if a solution exists using SnakeYAML, that would be ideal.
Upvotes: 2
Views: 926
Reputation: 2819
I've written the code in the form of a unit test, which parses exactly the file you provide using snakeYml
. Just run it.
@Test
void testYamlConvert() throws IOException {
// Step 1: Raad in file
var in = this.getClass().getResourceAsStream("/test.yml");
// System.out.println(in);
String yml = IOUtils.toString(in,"UTF-8");
// Step 2: Do in memory replacement to standard form
Pattern p = Pattern.compile("!!(.*)");
Matcher m = p.matcher(yml);
String ymlWithReplacement = yml;
while (m.find()) {
var nameToken = m.group().substring(2);
// System.out.println("Name token:"+nameToken);
ymlWithReplacement=ymlWithReplacement.replace("!!"+nameToken, "objectType: "+nameToken);
}
// System.out.println(ymlWithReplacement);
// Step 3: Do the parse ...
Yaml yaml = new Yaml();
var myYamlMap = (Map<String,Object>) yaml.load(ymlWithReplacement);
for(var entry : myYamlMap.entrySet()) {
System.out.println("Key:" + entry.getKey() + "Value:" + entry.getValue());
}
}
Here's how the resulting map looks like.
It should be very easy to get the necessary data from here. The principle of work is explained in the comments.
If you need something else for me to be able to claim the bounty, let me know !
Upvotes: 3
Reputation: 54
Try this,
ControlGroup controlGroup = yaml.load(url);
controlGroup.setObjectType(ControlGroup.class.getName());
System.out.println(yaml.dumpAsMap(controlGroup));
public class ControlGroup {
String objectType = this.getClass().getTypeName();
String name;
public ControlGroup() {};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getObjectType()
{
return this.getClass().getTypeName();
}
public void setObjectType(String className)
{
this.objectType = className;
}
}
MAP -->
name: myGroup
objectType: ControlGroup
Upvotes: 0
Reputation: 54
what worked was this,
!!ControlGroup
name: myGroup
controls:
- !!Button
name: button1
size: 10
- !!Knob
name: knob1
maxValue: 11
size: 7
Yaml yaml = new Yaml();
InputStream url = SnakeYml.class.getClassLoader().getResourceAsStream("sample.yaml");
Map<String, Object> obj = yaml.load(url);
System.out.println(obj);
public class ControlGroup {
String name;
public ControlGroup() {};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
....
Upvotes: 2