I'm a bit confused, how do I quickly retrieve a property from a loaded Yaml
SnakeYAML object? I shouldn't have to traverse through maps etc., right?
e.g.
app:
ftp:
host: 1.1.1.1
I read in my file
Yaml yaml = new Yaml();
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("application-test.yaml");
Map<String, Object> obj = yaml.load(inputStream);
inputStream.close();
and now I should be able to quickly do something like
obj.get("app").get("ftp").get("host")
or
yaml.get("app.ftp.host")
right? But there are errors: Something has to be cast to a Linked Hash Map, or there has to be iteration of fields, etc. I don't want to iterate anything myself, I want to quickly get a nested property with some kind of getter.
Why do I have to do this craziness to get a nested property even with the SnakeYaml library added to the project?
Yaml yaml = new Yaml();
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("application-test.yaml");
Map<String, Object> obj = yaml.load(inputStream);
inputStream.close();
LinkedHashMap objLevel1 = (LinkedHashMap)obj.get("app");
LinkedHashMap objLevel2 = (LinkedHashMap)objLevel1.get("sftp");
Integer port = (Integer)objLevel2.get("port");
Define the layout of the data in your file with classes:
class Ftp {
public String host;
public int port;
}
class App {
public Ftp ftp;
}
class Data {
public App app;
}
Then you can do
Data data = yaml.loadAs(inputStream, Data.class);
String host = data.app.ftp.host;
int port = data.app.ftp.port;
If you don't want to do that, you can always write a getter yourself:
<T> T getFromYaml(InputStream input, String[] path, Class<T> type) {
Yaml yaml = new Yaml();
Object data = yaml.load(inputStream);
for (String item: path) {
Map map = (Map) data;
data = map.get(item);
}
return (T) data;
}
// and then in your loading code:
try (InputStream inputStream = getClass().getResourceAsStream("/application-test.yaml")) {
Integer port = getFromYaml(inputStream, new String[] {"app", "ftp", "port"}, Integer.class);
// do something with it
}
The first method is preferred since SnakeYAML can yield good error messages, for example if the port
value is not an integer or ftp
is not a mapping. The second method will leave you alone with a casting exception (you can of course expand it to output good error messages).