【问题标题】:Providing default value on typesafe config getters为类型安全的配置获取器提供默认值
【发布时间】:2018-09-03 06:22:53
【问题描述】:
所以我的代码中多次出现类似的 sn-ps:
val optionValue = try {
Some(config.getString(key))
} catch {
case _: Missing => None
}
我想以某种方式从我的代码中消除这些重复项。我知道 typesafe 提供了一种方法来提供回退配置文件以提供默认配置值。但是,就我而言,某些属性没有任何默认值。它们是可选属性。
重构此代码的最佳方式是什么。
【问题讨论】:
标签:
scala
refactoring
typesafe
【解决方案2】:
由于您使用的是 Scala,并且假设您可以使用implicits,我会推荐使用丰富类的方法,它允许您保留Option 语法。
示例配置。
existent.sample.string="I exist!"
existent.sample.boolean=true
示例扩充类。
package config
import com.typesafe.config.{Config, ConfigException}
object MyConfig {
implicit class RichConfig(val config: Config) extends AnyVal {
def optionalString(path: String): Option[String] = if (config.hasPath(path)) {
Some(config.getString(path))
} else {
None
}
def optionalBoolean(path: String): Option[Boolean] = if (config.hasPath(path)) {
Some(config.getBoolean(path))
} else {
None
}
// An example of using the exception approach - but less efficient than using hasPath
def optionalString2(key: String): Option[String] = try {
Some(config.getString(key))
} catch {
case _: ConfigException => None
}
}
}
请注意,最好使用hasPath(而不是使用Try)来检查您的场景中是否存在密钥,而不是让JVM创建一个对可选配置不感兴趣的异常。允许不存在。
演示。
import com.typesafe.config._
object ConfigTest extends App {
import MyConfig._
val conf = ConfigFactory.load
val optionalString = conf.optionalString("existent.sample.string")
val optionalStringNone = conf.optionalString("non-existent.sample.string")
println(s"String config value: $optionalString")
println(s"Optional (non-existent) String config value: $optionalStringNone")
val optionalBoolean = conf.optionalBoolean("existent.sample.boolean")
val optionalBooleanNone = conf.optionalBoolean("non-existent.sample.boolean")
println(s"Boolean config value: $optionalBoolean")
println(s"Optional (non-existent) String config value: $optionalBooleanNone")
}
打印。
// String config value: Some(I exist!)
// Optional (non-existent) String config value: None
// Boolean config value: Some(true)
// Optional (non-existent) String config value: None
docs
【解决方案3】:
根据 Jacko 的回复,我更愿意简化代码并避免为每种类型复制和粘贴 hasPath 方法。
implicit class RichConfig(val config: Config) extends AnyVal {
private def getOptional[T](path: String, get: String => T): Option[T] = {
if (config.hasPath(path)) {
Some(get(path))
} else {
None
}
}
def optionalString(path: String): Option[String] = getOptional(path, config.getString)
def optionalInt(path: String): Option[Int] = getOptional(path, config.getInt)
def optionalDouble(path: String): Option[Double] = getOptional(path, config.getDouble)
def optionalBoolean(path: String): Option[Boolean] = getOptional(path, config.getBoolean)
}
【解决方案4】:
config.hasPath('sample.property') 会告诉你属性是否存在。
【解决方案5】:
我有类似的问题,这是我的解决方案,希望你喜欢它:
Try(key).map(config.getString).map(Some(_)).getOrElse(None)