提供类型安全配置获取器的默认值

时间:2018-09-03 06:22:54

标签: scala refactoring typesafe

所以我的代码中多次出现类似的片段:

val optionValue = try {
      Some(config.getString(key))
    } catch {
      case _: Missing => None
    }

我想以某种方式从我的代码中消除此重复项。我知道typesafe提供了一种方法来提供备用配置文件以提供默认配置值。但是,就我而言,我没有某些属性的任何默认值。它们是可选属性。

重构此代码的最佳方法是什么。

5 个答案:

答案 0 :(得分:0)

由于您使用的是Scala,并且假定您可以使用隐式,所以我建议使用一种使用丰富类的推荐方法,该类可以使您保留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

答案 1 :(得分:0)

根据https://github.com/lightbend/config#how-to-handle-defaults,这不是库的工作方式。

您应该使用withFallback方法来提供干净的配置。

答案 2 :(得分:0)

config.hasPath('sample.property')会告诉您该属性是否存在。

答案 3 :(得分:0)

根据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 :(得分:0)

我有类似的问题,这是我的解决方案,希望您喜欢:

Try(key).map(config.getString).map(Some(_)).getOrElse(None)