65

This is the first time I am working with YAML files, so the first think I looked at was to find any library that could help me to parse the file.

I have found two libraries, YamlBean and SnakeYAML. I am not sure which one that I am going to use.

Here is an example of the file that I am trying to parse:

users:
  user1:
    groups:
    - Premium
  user2:
    groups:
    - Mod
  user3:
    groups:
    - default
groups:
  Mod:
    permissions:
      test: true
    inheritance:
    - Premium
  default:
    permissions:
      test.test: true
    inheritance:
    - Mod
  Admin:
    permissions:
      test.test.test: true
    inheritance:
    - Mod

The file will change dynamical so I don't know how many users or groups the file would contain.

The information I would like to fetch from this is the user name and the group like this:

user1 Premium
user2 Mod
user3 default

And from the groups only the group names, like this:

Mod
default
Admin

Anyone could get me started here? And what is the best library to use for this? YamlBean or SnakeYAML?

I guess, I need to save the information in something that I easily could iterate over.

Lii
  • 11,553
  • 8
  • 64
  • 88
Kristoffer Isaksson
  • 881
  • 1
  • 6
  • 15

4 Answers4

66

You could also use Jacksons YAML module.

In order to use that, you'll need a few classes. The model classes which will carry the content of your file and the a class that takes care of reading the YAML file.

The root model class could look like this:

public class MyYamlFile {
    @JsonProperty
    private List<User> users;
    @JsonProperty
    private List<Group> groups;

    // getter methods ommitted
}

The User(*) class:

public class User {
    @JsonProperty
    private List<String> name;
    @JsonProperty
    private List<GroupType> groups;

    // getter methods ommitted
}

The GroupType could be an Enum containing all possible group types:

public enum GroupType {
    Premium, Mod, Default
}

Don't forget that the enum entries are case sensitive. So "premium" won't work. You can build all your model classes that way. Every sub entry should get an own model class.

Now to the part where you can read that YAML file:

public MyYamlFile readYaml(final File file) {
    final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); // jackson databind
    return mapper.readValue(file, MyYamlFile.class);
}

As you can see, this part is really neat, because you don't need much. The file instance contains your YAML file. You can create one like this:

File file = new File("path/to/my/yaml/usersAndGroups.yaml");

Instead of File the readValue method also supports InputStream, java.io.Reader, String (with the whole content), java.net.URL and byte array. You should find something that suits you.

(*) You should consider changing the structure of your YAML file, because I don't think it is possible to use dynamic keys with Jackson (maybe someone knows more about that):

users: 
    - name: user1
      groups:
        - Premium
    - name: user2
      groups:
        - Mod
    - name: user3
      groups:
        - Default
groups:
    ....
kenny_k
  • 3,831
  • 5
  • 30
  • 41
Tom
  • 16,842
  • 17
  • 45
  • 54
  • 4
    Thanks for letting me know of Jacksons YAML module. one problem is that i do not have the possibility to change the yaml file, its created in another application and i am just going to read it. maybe it is possible to use this module anyway? – Kristoffer Isaksson Sep 12 '14 at 07:56
  • @KristofferIsaksson Yes you can try that. Read the answer of this question: http://stackoverflow.com/questions/17685508/jackson-de-serialiazation-with-unknow-dynamic-property as an example. You will need another class that takes the whole file as `List>`. `user1` would be a key "somewhere" in that map. – Tom Sep 12 '14 at 15:40
  • What about reading into map of maps: `public Map readYaml(final File file) { final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); return mapper.readValue(file, Map.class); }` – Marcin Gołębski Apr 22 '21 at 16:39
  • @MarcinGołębski When you want to do that, then you can, `ObjectMapper` should be able to do that for you. But it would make it harder to access the individual items from your data. – Tom Apr 22 '21 at 16:48
15

I ended up using SnakeYaml and made some split strings to solve my issue.

Loaded the yaml file to Object and then into a Map, then split the result from the Map into String[] and then in a for loop I read out the name from the String[]. I did the same with groups.

I know that there is better solutions out there but this is good enough for this project.

Thanks all for the replies.

Peter Hall
  • 53,120
  • 14
  • 139
  • 204
Kristoffer Isaksson
  • 881
  • 1
  • 6
  • 15
3

Found this helpful link that will parse the input without touching java code, if ever need to change the config

https://stackabuse.com/reading-and-writing-yaml-files-in-java-with-snakeyaml

InputStream inputStream = new FileInputStream(new File("src/main/resources/customer.yaml"));
Yaml yaml = new Yaml();
Map<String, Object> data = yaml.load(inputStream);
System.out.println(data);
Atihska
  • 4,803
  • 10
  • 56
  • 98
-1

YamlBean is included to DMelt Java numeric computational environment (http://jwork.org/dmelt/). You can create Yaml files using jhplot.io.HFileYAML class which creates a key-value map and save as yaml file.

Tina21
  • 9