12

I am new to YAML and have parse a YAML config file that looks like:

applications:
  authentication:
    service-version: 2.0
    service-url: https://myapp.corp/auth
    app-env: DEV
    timeout-in-ms: 5000
    enable-log: true

  service1:
    enable-log: true
    auth-required: true
    app-env: DEV
    timeout-in-ms: 5000
    service-url: https://myapp.corp/service1
    service-name: SomeService1
    service-version: 1.1
    service-namespace: http://myapp.corp/ns/service1

  service2:
    enable-log: true
    auth-required: true
    app-env: DEV
    timeout-in-ms: 5000
    service-url: https://myapp.corp/service2
    service-name: SomeService2
    service-version: 2.0
    service-namespace: http://myapp.corp/ns/service2

I have to parse to following Map structure

+==================================+
| Key              |               |
+==================================+
| authentication   | AuthConfig    |
+----------------------------------+
| service1         | ServiceConfig |
+----------------------------------+
| service2         | ServiceConfig |
+----------------------------------+

AuthConfig and ServiceConfig are the custom objects in our system.

Can someone provide some hints how to do it?

Niranjan
  • 2,601
  • 8
  • 43
  • 54
  • Maybe is not a valid answer but you can use YamlBeans instead: http://yamlbeans.sourceforge.net/ that seems better documented – Héctor Feb 05 '16 at 07:22
  • This project has been moved to GitHub and there they have very little documentation. In fact the documentations are worse than SnakeYaml. I may be missing something here, but do you have the links to YamlBeans documentation? – Niranjan Feb 05 '16 at 08:29
  • Yes, it has been moved: https://github.com/EsotericSoftware/yamlbeans In Github README there is an explanation of what you want to do. – Héctor Feb 05 '16 at 08:35

2 Answers2

8

There is a package for Java called Jackson that handles mapping between YAML (and JSON, and CSV, and XML) and Java objects. Most examples you will come across are for JSON, but the YAML link shows that switching is straight-forward. Everything goes through an ObjectMapper:

ObjectMapper mapper = new ObjectMapper(new YAMLFactory());

That can then be used to deserialize your object via reflection:

ApplicationCatalog catalog = mapper.readValue(yamlSource, ApplicationCatalog.class);

You would set up your classes something like this (I've made everything public for ease of example):

class ApplicationCatalog {
  public AuthConfig authentication;
  public ServiceConfig service1;
  public ServiceConfig service2;
}

class AuthConfig {
  @JsonProperty("service-version")
  public String serviceVersion;
  @JsonProperty("service-url")
  public String serviceUrl;
  @JsonProperty("app-env")
  public String appEnv;
  @JsonProperty("timeout-in-ms")
  public int timeoutInMs;
  @JsonProperty("enable-log")
  public boolean enableLog;
}

class ServiceConfig {
  ...
}

Notice the JsonProperty annotation which is renaming your Java field to YAML field. I find this the most convenient way of dealing with JSON and YAML in Java. I've also had to use the streaming API for really large objects.

Sergio
  • 3,317
  • 5
  • 32
  • 51
Alex Taylor
  • 8,343
  • 4
  • 25
  • 40
  • 3
    BTW, Jackson actually uses SnakeYAML under the hood for YAML. – Alex Taylor Feb 06 '16 at 10:03
  • Thanks for replying; I am aware of Jackson APIs. We are using this for our REST services. I am also aware of the jackson-yml package. But I didn't want to use another wrapper over snakeyml lib. I will post once I find a convincing solution. Anyways, appreciate your help. – Niranjan Feb 06 '16 at 13:01
  • Seems like this is indeed the most convenient solution, thanks! – jansohn Jul 11 '18 at 09:14
-2

So as you have the same properties in the Auth and Service configuration I simplified that in one class to show you here.

The YamlConfig class look like this:

public class YamlConfig {

  private Map<String, ServiceConfig> applications;

  //... getter and setters here
}

And the the Parser logic is something like that :

Yaml yaml = new Yaml(new Constructor(YamlConfig.class));
InputStream input = new FileInputStream(new File("/tmp/apps.yml"));
YamlConfig data = yaml.loadAs( input, YamlConfig.class);

I shared the full code in this gist: https://gist.github.com/marceldiass/f1d0e25671d7f47b24271f15c1066ea3

Marcel Dias
  • 4,271
  • 1
  • 14
  • 10
  • This is a sample for a modified code, not the OP's original request. OP's YAML file uses dash( - ) as the separation while yours is using camelCase. – Kasun Gajasinghe Feb 10 '18 at 03:37