当前位置: 首页 > 工具软件 > scala-yaml > 使用案例 >

Scala 读取 YAML 配置文件并转成 Map

游皓
2023-12-01

背景

在日常的开发中,我们经常需要读取配置文件,以便于程序的灵活配置。在 Java 中,读取 properties 文件是比较常见的操作,而读取 YAML 配置文件则是比较新的需求。

Scala 作为一门现代化的编程语言,当然也能够轻松地读取 YAML 配置文件。本篇文章将介绍 Scala 读取 YAML 配置文件的方法,以及如何将读取到的配置信息转换成 Scala 中的 Map 对象。

思路

在 Scala 中,读取 YAML 配置文件可以通过 org.yaml.snakeyaml 库来实现。这个库提供了 YAML 解析器 Yaml 和构造器 Constructor,我们可以使用它们来将 YAML 配置文件解析成一个 Map 对象。

读取 YAML 配置文件的具体思路如下:

  1. 首先通过 getClass.getResourceAsStream() 方法获取 YAML 配置文件的 InputStream。

  1. 然后通过 Yaml 解析器和 Constructor 构造器将 YAML 配置文件解析成一个 Java Map 对象。

  1. 根据需要获取 Java Map 对象中的某个节点。

  1. 将 Java Map 对象转换成 Scala Map 对象,以便于在 Scala 中使用。

下面我们来逐步实现这个思路。

解析 YAML 配置文件

首先,我们需要使用 Yaml 解析器和 Constructor 构造器将 YAML 配置文件解析成一个 Java Map 对象。

我们首先通过 getClass.getResourceAsStream() 方法获取 YAML 配置文件的 InputStream,然后使用 Yaml 解析器和 Constructor 构造器将 InputStream 解析成一个 Java Map 对象 yamlMap。注意,在这个过程中我们需要指定 Constructor 的参数类型为 util.Map[String, Any],这样解析出来的对象才是一个 java.util.Map 类型。

获取指定节点的键值对

在拿到整个 YAML 配置文件的 Java Map 对象之后,我们需要根据需要获取其中的某个节点。

使用 get() 方法从 Java Map 对象 yamlMap 中获取 db 节点的子节点 subMap。在这个过程中,我们需要将 yamlMap 强制转换成 java.util.Map 类型,以便于获取子节点的键值对。

将 Java Map 转换成 Scala Map

接下来,我们需要将 Java Map 对象 subMap 转换成 Scala Map 对象。

我们首先使用 JavaConverters 中的 asScala 方法将 Java Map 对象 subMap 转换成 Scala Map 对象。然后,我们使用 map() 方法将 Scala Map 对象中的所有值转换成字符串类型,以便于在 Scala 中使用。最后,我们将转换后的键值对存储到一个新的 Scala Map 对象 resMap 中。

完整的代码

综上所述,我们可以将上面的步骤整合成一个完整的工具类,如下所示:

import org.yaml.snakeyaml.Yaml  
import org.yaml.snakeyaml.constructor.Constructor  
  
import java.io.InputStream  
import scala.collection.JavaConverters.mapAsScalaMapConverter  
import scala.collection.mutable  
  
/**  
 * YamlUtils: 解析 YAML 配置文件的工具类  
 */  
object YamlUtils {  
  
  /**  
   * 获取 YAML 配置文件中指定节点下的所有键值对,并以 Map 的形式返回。  
   *  
   * @param yamlPath YAML 配置文件在 resource 目录下的路径。  
   * @param arr 指定节点的路径,例如 Array("a", "b", "c") 表示获取节点 a.b.c 下的所有键值对。  
   * @return 返回一个 mutable.HashMap[String, String] 类型的 Map,其中存储了指定节点下的所有键值对。  
   */  
  def getNodeMap(yamlPath: String, arr: Array[String]): mutable.HashMap[String, String] = {  
  
    // 1. 加载 YAML 配置文件,把 YAML 解析成 Map    val input: InputStream = getClass.getResourceAsStream(yamlPath)  
    val yaml: Yaml = new Yaml(new Constructor(classOf[java.util.Map[String, Any]]))  
    var yamlMap: java.util.Map[String, Any] = yaml.load(input).asInstanceOf[java.util.Map[String, Any]]  
  
    // 2. 根据指定的节点路径,逐层解析 YAML 配置文件  
    for (node <- arr) {  
      yamlMap = yamlMap.get(node).asInstanceOf[java.util.Map[String, Any]]  
    }  
  
    // 3. 将 Java Map 转换成 Scala Map,并且只保留 String 类型的键值对  
    val resMap = new mutable.HashMap[String, String]()  
    yamlMap.asScala.toMap.map {  
      // 只保留 String 类型的键值对  
      case (k: String, v: String) => resMap += (k -> v)  
      case (k: String, v: Any) => resMap += (k -> v.toString)  
    }  
  
    resMap  
  }  
}

在这个工具类中,我们通过 getNodeMap() 方法实现了读取 YAML 配置文件并将其转换成 Scala Map 对象的功能。在这个过程中,我们使用了 org.yaml.snakeyaml 库中的 Yaml 解析器和 Constructor 构造器,以及 Scala 中的 JavaConverters 类和 mutable.HashMap 类。

使用案例

有了以上的工具类,我们可以轻松解析 YAML 配置文件,并获取指定节点下的键值对。下面,我们以一个示例来展示如何使用 YamlUtils 工具类。

假设我们有一个 YAML 配置文件,内容如下:

# application.yml
server:
  port: 8080
  context-path: /api/v1
database:
  url: jdbc:mysql://localhost:3306/test_db
  username: root
  password: password

现在我们想获取 database 节点下的所有键值对。我们可以在 Scala 代码中按照以下方式调用 YamlUtils.getNodeMap() 方法:

import scala.collection.mutable

val arr = Array("database") // 指定节点路径
val resMap: mutable.HashMap[String, String] = YamlUtils.getNodeMap("/application.yml", arr) // 获取指定节点下的所有键值对

其中,/application.yml 表示 YAML 配置文件在 resource 目录下的路径,arr 数组表示节点路径,即 database 节点。

最后,我们可以打印输出获取到的键值对,代码如下:

resMap.foreach { case (k, v) => println(s"$k: $v") }

输出结果如下:

url: jdbc:mysql://localhost:3306/test_db
username: root
password: password

总结

YAML 是一种轻量级的数据交换格式,被广泛应用于配置文件和数据传输。在 Scala 项目中,我们可以使用 YamlUtils 工具类轻松解析 YAML 配置文件,并获取指定节点下的键值对。这使得我们能够更加方便地管理和读取配置文件,提高了代码的可维护性和可读性。

 类似资料: