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
@BeanProperty
annotation. - The Snakeyaml library