configs is Scala wrapper for Typesafe config.
Add the following line to your build file:
libraryDependencies += "com.github.kxbmap" %% "configs" % "0.4.4"
configs version 0.4+ only support Java 8. If you need to Java 7, please check 0.3.x.
import com.typesafe.config.ConfigFactory
import configs.Configs
Result type of get a value from config is configs.Result
.
If get successfully, returns configs.Result.Success
, if not configs.Result.Failure
:
val config = ConfigFactory.parseString("foo = 42")
scala> val result = Configs[Int].get(config, "foo")
result: configs.Result[Int] = Success(42)
scala> result.valueOrElse(0)
res0: Int = 42
scala> val result = Configs[Int].get(config, "missing")
result: configs.Result[Int] = Failure(ConfigError(Exceptional(com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'missing',List(missing)),Vector()))
scala> result.valueOrElse(0)
res1: Int = 0
Import configs.syntax._
provides extension methods for Config
:
import configs.syntax._
scala> config.get[Int]("foo")
res2: configs.Result[Int] = Success(42)
get[Option[A]]
will return success with value None
if path is not exists:
scala> config.get[Option[Int]]("missing")
res3: configs.Result[Option[Int]] = Success(None)
scala> config.getOrElse("missing", 0) // Alias for config.get[Option[Int]]("missing").map(_.getOrElse(0))
res4: configs.Result[Int] = Success(0)
You can get a case class value out of the box:
import scala.concurrent.duration.FiniteDuration
case class MyConfig(foo: String, bar: Int, baz: List[FiniteDuration])
val config = ConfigFactory.parseString("""
my-config {
foo = My config value
bar = 123456
baz = [1h, 2m, 3s]
}
""")
scala> config.get[MyConfig]("my-config")
res6: configs.Result[MyConfig] = Success(MyConfig(My config value,123456,List(1 hour, 2 minutes, 3 seconds)))
If failed, Result
accumulates error messages:
val config = ConfigFactory.parseString("""
my-config {
bar = 2147483648
baz = [aaa, bbb, ccc]
}
""")
scala> val result = config.get[MyConfig]("my-config")
result: configs.Result[MyConfig] = Failure(ConfigError(Exceptional(com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'foo',List(my-config, foo)),Vector(Exceptional(com.typesafe.config.ConfigException$WrongType: String: 2: bar has type out-of-range value 2147483648 rather than int (32-bit integer),List(my-config, bar)), Exceptional(com.typesafe.config.ConfigException$BadValue: String: 4: Invalid value at '0': No number in duration value 'aaa',List(my-config, baz, 0)), Exceptional(com.typesafe.config.ConfigException$BadValue: String: 4: Invalid value at '1': No number in duration value 'bbb',List(my-config, baz, 1)), Exceptional(com.typesafe.config.ConfigException$BadValue: String: 4: Invalid value at '2': No number in duration v...
scala> result.valueOr { error =>
| error.messages.foreach(println)
| MyConfig("", 0, Nil)
| }
[my-config.foo] No configuration setting found for key 'foo'
[my-config.bar] String: 2: bar has type out-of-range value 2147483648 rather than int (32-bit integer)
[my-config.baz.0] String: 4: Invalid value at '0': No number in duration value 'aaa'
[my-config.baz.1] String: 4: Invalid value at '1': No number in duration value 'bbb'
[my-config.baz.2] String: 4: Invalid value at '2': No number in duration value 'ccc'
res7: MyConfig = MyConfig(,0,List())
You can get a value without key using extract
:
val config = ConfigFactory.parseString("""
foo = My config value
bar = 123456
baz = [1h, 2m, 3s]
""")
scala> config.extract[MyConfig]
res8: configs.Result[MyConfig] = Success(MyConfig(My config value,123456,List(1 hour, 2 minutes, 3 seconds)))
configs can get many type values from config.
It is provided by type class Configs
.
There are a number of built-in Configs
instances:
- Primitive/Wrapper types
Long
,Int
,Short
,Byte
,Double
,Float
,Char
,Boolean
java.lang.
{Long
,Integer
,Short
,Byte
,Double
,Float
,Character
,Boolean
}
- Big number types
BigInt
,BigDecimal
java.math.
{BigInteger
,BigDecimal
}
- String representation types
String
Symbol
,java.util.
{UUID
,Locale
}java.io.File
,java.nio.file.Path
java.net.
{URI
,InetAddress
}
- Duration types
java.time.Duration
scala.concurrent.duration.
{Duration
,FiniteDuration
}
- Config types
com.typesafe.config.
{Config
,ConfigValue
,ConfigList
,ConfigObject
,ConfigMemorySize
}configs.Bytes
- Enum types
- Java
enum
types - Scala
Enumeration
types
- Java
- Collection types
F[A]
(usingCanBuildFrom[Nothing, A, F[A]]
, e.g.List[String]
,Seq[Int]
)M[S, A]
(usingCanBuildFrom[Nothing, (S, A), M[S, A]]
, e.g.Map[String, Int]
,TreeMap[UUID, Config]
)java.util.
{List[A]
,Map[S, A]
,Set[A]
,Collection[A]
},java.lang.Iterable[A]
java.util.Properties
- Optional types
Option[A]
java.util.
{Optional[A]
,OptionalLong
,OptionalInt
,OptionalDouble
}
- case classes
- classes that have public constructors
- ADTs (sealed trait + classes/objects). See ADTs support
- Java Beans. See Java Beans support
In this list, A
means any type that is Configs
instance. And S
means any type that is FromString
instance.
If there is such an ADT:
sealed trait Tree
case class Branch(value: Int, left: Tree, right: Tree) extends Tree
case object Leaf extends Tree
You can get an ADT value from config:
val config = ConfigFactory.parseString("""
tree = {
type = Branch
value = 42
left = Leaf
right {
type = Branch
value = 123
left = Leaf
right = { type = Leaf }
}
}
""")
scala> config.get[Tree]("tree")
res9: configs.Result[Tree] = Success(Branch(42,Leaf,Branch(123,Leaf,Leaf)))
If there is Java Beans class like the follows:
@lombok.Data
public class MyBean {
private int intValue;
private java.util.List<String> stringList;
private java.util.Map<java.util.Locale, java.time.Duration> localeToDuration;
}
Then you define Configs
instance using deriveBean
macro:
implicit val myBeanConfigs: Configs[MyBean] =
Configs.deriveBean[MyBean]
And then you can get Java Beans value:
val config = ConfigFactory.parseString("""
int-value = 42
string-list = [foo, bar, baz]
locale-to-duration {
ja_JP = 42ms
en_US = 123s
}
""")
scala> config.extract[MyBean]
res10: configs.Result[MyBean] = Success(MyBean(intValue=42, stringList=[foo, bar, baz], localeToDuration={en_US=PT2M3S, ja_JP=PT0.042S}))
Copyright 2013-2016 Tsukasa Kitachi
Apache License, Version 2.0