首页 > 解决方案 > Pureconfig 将配置读取为属性映射

问题描述

是否可以将 pureconfig 读取属性设置为Map[String, String]?我有以下

application.conf

cfg{
  some.property.name: "value"
  some.another.property.name: "another value"
}

这是我尝试读取配置的应用程序:

import pureconfig.generic.auto._
import pureconfig.ConfigSource
import pureconfig.error.ConfigReaderException

object Model extends App {
  case class Config(cfg: Map[String, String])

  val result = ConfigSource.default
    .load[Config]
    .left
    .map(err => new ConfigReaderException[Config](err))
    .toTry

  val config = result.get
  println(config)
}

问题是它引发了以下异常:

Exception in thread "main" pureconfig.error.ConfigReaderException: Cannot convert configuration to a Model$Config. Failures are:
  at 'cfg.some':
    - (application.conf @ file:/home/somename/prcfg/target/classes/application.conf: 2-3) Expected type STRING. Found OBJECT instead.

    at Model$.$anonfun$result$2(Model.scala:11)
    at scala.util.Either$LeftProjection.map(Either.scala:614)
    at Model$.delayedEndpoint$Model$1(Model.scala:11)
    at Model$delayedInit$body.apply(Model.scala:5)
    at scala.Function0.apply$mcV$sp(Function0.scala:39)
    at scala.Function0.apply$mcV$sp$(Function0.scala:39)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
    at scala.App.$anonfun$main$1(App.scala:73)
    at scala.App.$anonfun$main$1$adapted(App.scala:73)
    at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:553)
    at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:551)
    at scala.collection.AbstractIterable.foreach(Iterable.scala:920)
    at scala.App.main(App.scala:73)
    at scala.App.main$(App.scala:71)
    at Model$.main(Model.scala:5)
    at Model.main(Model.scala)

有没有办法解决它?我预计Map[String, String]将包含以下映射:

some.property.name -> "value"
some.another.property.name -> "another value"

标签: scalapureconfig

解决方案


你的问题不是纯配置。你的问题是你写的 HOCON 规范:

cfg {
  some.property.name: "value"
  some.another.property.name: "another value"
}

是语法糖:

cfg {
  some {
    property {
      name = "value"
    }
  }
  
  another {
    property {
      name = "another value"
    }
  }
}

是 TypeSafe Config/Lightbend Config 决定你cfg有两个属性并且它们都是嵌套配置。Pureconfig 只接受这些嵌套配置并将它们映射到案例类。但它无法映射结构与预期完全不同的东西。

如果你写:

cfg {
  some-property-name: "value"
  some-another-property-name: "another value"
}

您将能够将"cfg"路径解码为Map[String, String]并将顶级配置解码为case class Config(cfg: Map[String, String]). 如果您想将其.视为键的一部分而不是嵌套...那么恐怕您必须ConfigReader自己编写一个,因为那是非标准用法。


推荐阅读