代码之家  ›  专栏  ›  技术社区  ›  vatsal mevada

提供typesafe配置getter的默认值

  •  1
  • vatsal mevada  · 技术社区  · 8 年前

    因此,我的代码中多次出现类似的代码片段:

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

    我想以某种方式消除代码中的重复项。我知道typesafe提供了一种方法来提供一个回退配置文件来提供默认的配置值。但是,在我的例子中,我没有一些属性的默认值。它们是可选属性。

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

    2 回复  |  直到 8 年前
        1
  •  4
  •   jacks    8 年前

    既然您使用的是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

        2
  •  7
  •   Thomas Decaux    7 年前
        3
  •  2
  •   Franzi    7 年前

    从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
  •  1
  •   AlexanderAdam    7 年前

        5
  •  0
  •   Michal Przysucha    6 年前

    我也遇到过类似的问题,这是我的解决方案,希望您喜欢:

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