[英]scala read config to Map of Map of case class
I need to read from a config file and map the config to a case class .It works fine if i have one table as below我需要从一个配置文件中读取并将配置映射到一个案例类。如果我有一个如下表,它工作正常
CONFIG配置
mapping {
target {
oracle = {
type = "oracle"
schema = "orcl"
tableName = "my_table"
query = "select key from my_table where dob='2020-01-01'
}
}
SCALA CODE SNIPPET SCALA 代码片段
val targetConfig:Map[String,QueryEngine] = config.getObject("mapping.target")
.entrySet()
.asScala
.foldLeft(Map.empty[String , QueryEngine]) { case ( acc , entry ) =>
val target = entry.getKey
val targetConfig = entry.getValue match {
case validElement if validElement.valueType() == ConfigValueType.OBJECT => validElement.asInstanceOf[ConfigObject].toConfig
case invalidElement => sys.error("illegal syntax at $invalidElement")
}
targetConfig.getString("type") match {
case "oracle" => acc + (target -> new OracleQueryEngine(vars,target,targetConfig.getString("schema"),targetConfig.getString("tableName"),targetConfig.getString("query"),targetConfig.getString("param")))
case x => sys.error(s"unknow target not defined $targetConfig with $targetConfig")
}
}
NOW i updated CONFIG with MULTIPLE tables in the target mapping.现在我用目标映射中的 MULTIPLE 表更新了 CONFIG。
mapping {
target {
oracle =
emp = {
type = "oracle"
schema = "orcl"
tableName = "emp"
query = "select key from emp where dob='2020-01-01'
}
dept = {
type = "oracle"
schema = "orcl"
tableName = "dept"
query = "select key from dept where dob='2020-01-01'
}
}
}
CODE SNIPPET for the multiple table scenario This is giving error Expression of mutable.Set[Map[String,QueryEngine]] doesnt confirm to Map[Query,String]多表场景的代码片段这给出了 mutable.Set[Map[String,QueryEngine]] 的错误表达式不确认 Map[Query,String]
val targetConfig:Map[String,QueryEngine] = config.getObject("mapping.target")
.entrySet()
.asScala
.foldLeft(Map.empty[String , QueryEngine]) { case ( acc , entry ) =>
val target = entry.getKey
val targetConfig = entry.getValue match {
case validElement if validElement.valueType() == ConfigValueType.OBJECT => validElement.asInstanceOf[ConfigObject].toConfig
case invalidElement => sys.error("illegal syntax at $invalidElement")
}
targetConfig.getObject(s"mapping.target.$target").keySet().asScala.map { key =>
target match {
case "oracle" => acc + (target -> new OracleQueryEngine(vars,target,targetConfig.getString("schema"),targetConfig.getString("tableName"),targetConfig.getString("query"),targetConfig.getString("param")))
case x => sys.error(s"unknow target not defined $targetConfig with $targetConfig")
}
}
}
PURE CONFIG CODE纯配置代码
import pureconfig._
import pureconfig.generic.ProductHint
import pureconfig.generic.auto._
import com.typesafe.config.ConfigFactory
import pureconfig._
import pureconfig.generic.auto._
object PureconfigExample {
case class QueryEngine(`type`: String, schema: String, tableName: String, query: String)
type DatabaseConfig = Map[String, Map[String, QueryEngine]]
case class TargetConfig(target: DatabaseConfig)
case class ApplicationConfig(mapping: TargetConfig)
def main(args: Array[String]): Unit = {
val configString =
"""
|mapping {
| target {
| oracle {
| emp {
| type = "oracle"
| schema = "orcl"
| tableName = "emp"
| query = "select key from emp where dob='2020-01-01'"
| }
| dept {
| type = "oracle"
| schema = "orcl"
| tableName = "dept"
| query = "select key from dept where dob='2020-01-01'"
| }
| }
| }
|}
|""".stripMargin
import pureconfig.generic.auto._
// See for more details - https://pureconfig.github.io/docs/overriding-behavior-for-case-classes.html
implicit def hint[T]: ProductHint[T] = ProductHint[T](ConfigFieldMapping(CamelCase, CamelCase))
val config = ConfigSource.string(configString).load[ApplicationConfig]
println(config)
}
}
POM.XML POM文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test2</groupId>
<artifactId>test2</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.github.pureconfig</groupId>
<artifactId>pureconfig-generic-base_2.12</artifactId>
<version>0.12.2</version>
</dependency>
<dependency>
<groupId>com.github.pureconfig</groupId>
<artifactId>pureconfig-generic_2.12</artifactId>
<version>0.12.0</version>
</dependency>
</dependencies>
</project>
COMPILER ERROR编译器错误
PureConfigExample.scala
Error:(43, 56) Cannot find an implicit instance of pureconfig.ConfigReader[PureconfigExample.ApplicationConfig].
If you are trying to read or write a case class or sealed trait consider using PureConfig's auto derivation by adding `import pureconfig.generic.auto._`
val config = ConfigSource.string(configString).load[ApplicationConfig]
Error:(43, 56) not enough arguments for method load: (implicit reader: pureconfig.Derivation[pureconfig.ConfigReader[PureconfigExample.ApplicationConfig]])pureconfig.ConfigReader.Result[PureconfigExample.ApplicationConfig].
Unspecified value parameter reader.
val config = ConfigSource.string(configString).load[ApplicationConfig]
Excuse me, for probably, not the answer you probably expected, but I strongly encourage avoid manual config parsing, because there are tools that doing it for you automatically, without boiler-plate code and type-safe at the same time.对不起,可能不是您可能期望的答案,但我强烈建议您避免手动配置解析,因为有一些工具可以自动为您执行此操作,同时无需样板代码和类型安全。 The most popular and probably the best library in Scala eco-system is PureConfig . Scala 生态系统中最受欢迎且可能是最好的库是PureConfig 。 So in you case the solution would look like something like this:所以在你的情况下,解决方案看起来像这样:
import pureconfig._
import pureconfig.generic.ProductHint
import pureconfig.generic.auto._
object PureconfigExample {
case class QueryEngine(`type`: String, schema: String, tableName: String, query: String)
type DatabaseConfig = Map[String, Map[String, QueryEngine]]
case class TargetConfig(target: DatabaseConfig)
case class ApplicationConfig(mapping: TargetConfig)
def main(args: Array[String]): Unit = {
val configString =
"""
|mapping {
| target {
| oracle {
| emp {
| type = "oracle"
| schema = "orcl"
| tableName = "emp"
| query = "select key from emp where dob='2020-01-01'"
| }
| dept {
| type = "oracle"
| schema = "orcl"
| tableName = "dept"
| query = "select key from dept where dob='2020-01-01'"
| }
| }
| }
|}
|""".stripMargin
// See for more details - https://pureconfig.github.io/docs/overriding-behavior-for-case-classes.html
implicit def hint[T]: ProductHint[T] = ProductHint[T](ConfigFieldMapping(CamelCase, CamelCase))
val config = ConfigSource.string(configString).load[ApplicationConfig]
println(config)
}
}
which in my case produces next result:在我的情况下产生下一个结果:
Right(ApplicationConfig(TargetConfig(Map(oracle -> Map(emp -> QueryEngine(oracle,orcl,emp,select key from emp where dob='2020-01-01'), dept -> QueryEngine(oracle,orcl,dept,select key from dept where dob='2020-01-01'))))))
Hope this help!希望这有帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.