While not apparent from the quick start samples in the README its pretty painless to derive a map of values from HOCON.
In the domain I'm modeling there are some devices identified by a name that represent a UDP socket address. I end up with a resources/reference.conf that contains the following:
decoders = [ { a : "socket://1.2.3.4:9000" }, { b : "socket://1.2.3.4:8080" }, { c : "socket://9.9.9.9:9001" }, { d : "socket://9.9.8.8:9000" }, { e : "socket://4.3.2.1:8081" } ]
Then I wrote a class to encapsulate the settings in a type safe way:
import com.typesafe.config.{ConfigObject, ConfigValue, ConfigFactory, Config} import scala.collection.JavaConverters._ import java.net.URI import java.util.Map.Entry case class Settings(config: Config) { lazy val decoders : Map[String, URI] = { val list : Iterable[ConfigObject] = config.getObjectList("decoders").asScala (for { item : ConfigObject <- list entry : Entry[String, ConfigValue] <- item.entrySet().asScala key = entry.getKey uri = new URI(entry.getValue.unwrapped().toString) } yield (key, uri)).toMap } }
The for-comprehension requires a little bit more explanation: its similar to writing nested foreach constructs in imperative languages (i.e., foreach (item : list) { foreach (entry : item.entrySet()) { ... } }) and exposes the state of each iteration of each loop to the statements that appear below their declarations. You could arrive at the same result using maps and lambdas but I feel that this code is easier to read and comprehend.
It is possible in the above code for each entry to contain a collection of child entries = i.e., the outer array isn't strictly necessary (except for the fact that the code invokes getObjectList) but I decided to isolate each entry into its own map for config file readability.