This is an excerpt from the Scala Cookbook. This is Recipe 12.6, “How to read a YAML configuration file in Scala.”
Problem
You need to read a YAML configuration file in a Scala application.
Update
In Scala 2.12 and 2.13, BeanProperty can now be found as scala.beans.BeanProperty.
Solution
At the time of this writing, there are no custom Scala libraries for reading YAML files, so use the Java Snakeyaml library, as shown in the following example. Snakeyaml requires that a class conform to the JavaBeans specification, so the EmailAccount class uses the @BeanProperty annotation for all of its fields:
import org.yaml.snakeyaml.Yaml
import org.yaml.snakeyaml.constructor.Constructor
import scala.collection.mutable.ListBuffer
import scala.reflect.BeanProperty
import java.io.{File, FileInputStream}
object YamlBeanTest {
def main(args: Array[String]) {
val filename = "/foo/config.yaml"
val input = new FileInputStream(new File(filename))
val yaml = new Yaml(new Constructor(classOf[EmailAccount]))
val e = yaml.load(input).asInstanceOf[EmailAccount]
println(e)
}
}
/**
* With the Snakeyaml Constructor approach shown in the main method,
* this class must have a no-args constructor.
*/
class EmailAccount {
@BeanProperty var accountName = ""
@BeanProperty var username = ""
@BeanProperty var password = ""
@BeanProperty var mailbox = ""
@BeanProperty var imapServerUrl = ""
@BeanProperty var protocol = ""
@BeanProperty var minutesBetweenChecks = 0
@BeanProperty var usersOfInterest = new java.util.ArrayList[String]()
override def toString: String = s"acct: $accountName, user: $username, url: $imapServerUrl"
}
This code is written to read a YAML file with the following fields:
accountName: Ymail Account username: johndoe password: secret mailbox: INBOX imapServerUrl: imap.mail.yahoo.com protocol: imaps minutesBetweenChecks: 1 usersOfInterest: [barney, betty, wilma]
Discussion
You can also create a class with @BeanProperty fields as constructor arguments. The following example is a Scala version of the Java example shown in the Snakeyaml documentation. In this code, I load the sample data from a String (instead of a file) which is a nice feature of the Snakeyaml library that’s very useful for testing:
package yaml
import org.yaml.snakeyaml.Yaml
import scala.reflect.BeanProperty
object YamlBeanTest2 {
def main(args: Array[String]) {
val data = "--- !!yaml.Person [ David, Moore, 22 ]"
val yaml = new Yaml
val obj = yaml.load(data)
val person = obj.asInstanceOf[Person]
println(person)
}
}
/**
* With the approach shown in the main method -- load() plus
* asInstanceOf -- this class must declare its properties in the
* constructor.
*/
// snakeyaml requires properties to be specified in the constructor
class Person(@BeanProperty var firstName: String,
@BeanProperty var lastName: String,
@BeanProperty var age: Int) {
override def toString = s"$firstName, $lastName, $age"
}
| this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |
See Also
- Recipe 17.6, “When Java Code Requires JavaBeans (from your Scala code)” provides more information on using the
@BeanPropertyannotation. - The Snakeyaml library