如何使用 spark/scala 解析 YAML

Posted

技术标签:

【中文标题】如何使用 spark/scala 解析 YAML【英文标题】:How to parse a YAML with spark/scala 【发布时间】:2019-11-11 17:35:20 【问题描述】:

我有包含以下详细信息的 yaml 文件。 文件名:config.yml

- firstName: "James"
  lastName: "Bond"
  age: 30

- firstName: "Super"
  lastName: "Man"
  age: 25

由此我需要使用带有 scala 的 spark 获取 spark 数据帧

+---+---------+--------+
|age|firstName|lastName|
+---+---------+--------+
|30 |James    |Bond    |
|25 |Super    |Man     |
+---+---------+--------+

我已尝试转换为 json,然后转换为数据框,但我无法在数据集序列中指定它。

【问题讨论】:

恐怕您必须为此编写一个自定义阅读器... YAML 是一种配置格式,因此没有标准方法可以将其作为数据源读取 你可以先把你的yaml转成json,然后再转成datframe,否则,就像ss301说的,你得自己写个自定义阅读器。 是的,我试过了,但它返回为 Right([json code])。如何将其转换为实际的 json? @DrissNejjar @Vincent YAML 是一种数据序列化格式,见 yaml.org 【参考方案1】:

有一个解决方案,可以帮助您将 yaml 转换为 json,然后将其作为 DataFrame 读取

你需要添加这2个依赖:

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
class ScalaYamltoDataFrame 

val yamlExample = "- firstName: \"James\"\n  lastName: \"Bond\"\n  age: 30\n\n- firstName: \"Super\"\n  lastName: \"Man\"\n  age: 25"

  def convertYamlToJson(yaml: String): String = 
    val yamlReader = new ObjectMapper(new YAMLFactory)
    val obj = yamlReader.readValue(yaml, classOf[Any])
    val jsonWriter = new ObjectMapper
    jsonWriter.writeValueAsString(obj)
  

  println(convertYamlToJson(yamlExample))

  def yamlToDF(): Unit = 

    @transient
    lazy val sparkSession = SparkSession.builder
      .master("local")
      .appName("Convert Yaml to Dataframe")
      .getOrCreate()

    import sparkSession.implicits._

    val ds  = sparkSession.read
      .option("multiline", true)
      .json(Seq(convertYamlToJson(yamlExample)).toDS)


    ds.show(false)

    ds.printSchema()
  

//println(convertYamlToJson(yamlExample))
["firstName":"James","lastName":"Bond","age":30,"firstName":"Super","lastName":"Man","age":25]

//ds.show(false)
+---+---------+--------+
|age|firstName|lastName|
+---+---------+--------+
|30 |James    |Bond    |
|25 |Super    |Man     |
+---+---------+--------+


//ds.printSchma()
root
 |-- age: long (nullable = true)
 |-- firstName: string (nullable = true)
 |-- lastName: string (nullable = true)

希望这会有所帮助!

【讨论】:

好的,这行得通。谢谢。我从如此使用的文件中读取 - `val fileContents = Source.fromFile("path/config.yml").getLines.mkString(sep = "\n") ` 我在年龄之后也有一个生日日期列,但它是数据框中的第一个列。知道为什么会这样吗?有没有办法自己订购数据集? 我不确定顺序是否相关,因为数据集是不可变的,您可以通过它的名称来调用它。你可以查看这个 *** 帖子:***.com/questions/38104600/…

以上是关于如何使用 spark/scala 解析 YAML的主要内容,如果未能解决你的问题,请参考以下文章

如何在Spark Scala中以CSV格式编写不同的布局

Spark Scala - 如何为每个组创建新列,然后在 spark 数据框中分解列值

如何在 Spark/Scala 中使用 countDistinct?

如何使用 Spark/Scala 在 HDFS 上编写/创建 zip 文件?

如何使用 spark/scala 检查是不是存在大查询表

如果其他,Spark scala udf 错误