YAML (YAML Ain‘t Markup Language) is a popular data serialization language used for configuration files and data storage. Its main advantages are readability and ease of use compared to other formats like JSON or XML.

In this comprehensive guide, we will explore parsing YAML files in Java using the SnakeYAML library. We will cover:

  • What is YAML and why parse it in Java
  • Adding SnakeYAML dependency
  • Reading a simple YAML file
  • Reading nested YAML data structures
  • Mapping YAML data to custom Java objects
  • Handling syntax errors and exceptions

What is YAML and Why Parse it in Java

YAML is used to store structured data including lists, maps and primitive data types in a format that is friendly for humans to read and write.

Here is an example YAML file:

firstName: John
lastName: Doe
age: 35
address:
  line1: 123 Main St
  city: Anytown
  state: CA
  zip: 12345
items:
  - apple
  - orange
  - banana

As you can see, YAML uses basic formatting like spaces, colons and dashes rather than braces and brackets like JSON or tags like XML. This makes YAML ideal for configuration files.

Common uses of YAML include:

  • Application configuration files
  • Storing data for applications
  • As an alternative to JSON or XML
  • Kubernetes resource definitions
  • Ansible playbooks

In many projects, we need to read data from a YAML file and make it available to a Java application. This is where parsing comes in.

There are a few libraries available for parsing YAML in Java. In this tutorial we will use SnakeYAML which is compact, dependency-free and very easy to use.

Adding the SnakeYAML Dependency

To use SnakeYAML, add the following Maven dependency to your pom.xml:

<dependency>
  <groupId>org.yaml</groupId>
  <artifactId>snakeyaml</artifactId>
  <version>1.33</version>
</dependency>

Or if using Gradle:

implementation ‘org.yaml:snakeyaml:1.33‘

This will download SnakeYAML along with its own dependencies.

Reading a Simple YAML File

Let‘s start by parsing a simple YAML file in Java using SnakeYAML:

import org.yaml.snakeyaml.Yaml;
import java.util.Map;
import java.util.LinkedHashMap;

public class Application {

  public static void main(String[] args) {

    // Load the YAML file data
    InputStream inputStream = new FileInputStream("data.yaml"); 
    Yaml yaml = new Yaml();
    Map<String,Object> data = yaml.load(inputStream);

    // Print the data
    System.out.println(data);

  }

}

The data.yaml file contains:

name: John Doe
age: 35
address: 123 Main Street, Anytown

When we run the application, SnakeYAML will parse the YAML content and store it in a Map with string keys and object values:

{name=John Doe, age=35, address=123 Main Street, Anytown}

We can see the YAML properties mapped neatly as key-value pairs in the Map.

To access a specific property, use:

String name = (String)data.get("name"); 

Since all values are Object typed, we have to cast to the correct type like String or Integer.

Reading Nested YAML Objects

In addition to simple keys and values, YAML also supports nesting objects and collections like lists and maps.

Here is an example with nested data:

person:
  name: John Doe
  age: 35
  address: 
    line1: 123 Main St
    city: Anytown
    state: CA
items:
  - apple
  - orange
  - banana

We can use the same SnakeYAML parsing code as before without any changes to load this nested content.

Accessing the nested address would look like:

Map<String,Object> address = (Map<String,Object>)data.get("person").get("address");
String city = (String)address.get("city"); // Anytown

And the items list:

List<String> items = (List<String>)data.get("items");
String item1 = items.get(0); // apple

So SnakeYAML handles nested structures in YAML seamlessly.

Mapping YAML to Custom Java Objects

For complex YAML data models, it is better to parse and map the data to custom domain objects rather than using basic Maps and Lists.

For example, consider this YAML document describing a person:

firstName: John  
lastName: Doe
age: 35
address: 
  line1: 123 Main St
  city: Anytown
  state: CA
  zip: 33333

Let‘s define a Person class with matching attributes:

public class Person {

    private String firstName;
    private String lastName;

    private int age;  

    private Address address;

    // Constructors, getters and setters 

}

public class Address {

    private String line1;
    private String city;
    private String state;
    private String zip;

    // Constructors, getters and setters

}

Now while parsing, we specify the target Java type and SnakeYAML will automatically map YAML properties to object attributes:

Yaml yaml = new Yaml(new Constructor(Person.class));
InputStream inputStream = new FileInputStream("data.yaml");

Person person = yaml.load(inputStream);

That‘s it! The person instance contains the parsed data from YAML. We can use normal Java code to access it:

System.out.println(person.getFirstName()); // John
System.out.println(person.getAddress().getState()); // CA

The mapping works if YAML attributes match the names of Java bean properties exactly.

Handling YAML Parsing Errors

When loading invalid YAML content, SnakeYAML will throw exceptions which we need to handle properly:

try {

  Yaml yaml = new Yaml();
  Map<String,Object> data = yaml.load(inputStream);

} catch(Exception e) {
  // Print error 
  e.printStackTrace();
}

Common errors include:

  • YamlException: Error parsing YAML syntax
  • ClassCastException: Unable to cast YAML values to expected Java types

We should catch these exceptions, print the error details and handle invalid/unexpected data.

For production use cases, log errors and fail gracefully instead of throwing raw exceptions to end users.

Conclusion

In this tutorial, we looked at:

  • Why YAML data serialization is useful for application configuration and data storage
  • Using SnakeYAML library for parsing YAML files in Java
  • Reading YAML as simple key-value maps or custom domain objects
  • Accessing nested objects and collections in YAML documents
  • Best practices for error handling

SnakeYAML provides an easy way to load YAML data in Java applications. With the power of Java, we can then manipulate the data however we need.

The full code for this tutorial is available on GitHub.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *