【问题标题】:How to access sub-entities in JSON file?如何访问 JSON 文件中的子实体?
【发布时间】:2022-03-03 05:17:58
【问题描述】:

我有一个如下所示的 json 文件:

{
  "employeeDetails":{
    "name": "xxxx",
    "num":"415"
  },
  "work":[
    {
      "monthYear":"01/2007",
      "workdate":"1|2|3|....|31",
      "workhours":"8|8|8....|8"
    },
    {
      "monthYear":"02/2007",
      "workdate":"1|2|3|....|31",
      "workhours":"8|8|8....|8"
    }
  ]
}

我必须从这个 json 数据中获取工作日期、工作时间。

我试过这样:

import org.apache.spark.{SparkConf, SparkContext}

object JSON2 {
  def main (args: Array[String]) {
    val spark =
      SparkSession.builder()
        .appName("SQL-JSON")
        .master("local[4]")
        .getOrCreate()

    import spark.implicits._

    val employees = spark.read.json("sample.json")
    employees.printSchema()
    employees.select("employeeDetails").show()
  }
}

我遇到这样的异常:

Exception in thread "main" org.apache.spark.sql.AnalysisException: cannot resolve '`employeeDetails`' given input columns: [_corrupt_record];;
'Project ['employeeDetails]
+- Relation[_corrupt_record#0] json

我是 Spark 的新手。

【问题讨论】:

    标签: scala apache-spark apache-spark-sql


    【解决方案1】:

    给定的输入列:[_corrupt_record];;

    原因是 Spark 支持 JSON 文件,其中 “每一行必须包含一个单独的、自包含的有效 JSON 对象。”

    引用JSON Datasets:

    请注意,作为 json 文件提供的文件不是典型的 JSON 文件。每行必须包含一个单独的、自包含的有效 JSON 对象。欲了解更多信息,请参阅JSON Lines text format, also called newline-delimited JSON。因此,常规的多行 JSON 文件通常会失败。

    如果 JSON 文件对于 Spark 不正确,它会将其存储在 _corrupt_record 下(您可以使用 columnNameOfCorruptRecord 选项进行更改)。

    scala> spark.read.json("employee.json").printSchema
    root
     |-- _corrupt_record: string (nullable = true)
    

    您的文件不正确,不仅因为它是多行 JSON,还因为 jq(轻量级且灵活的命令行 JSON 处理器)这样说。

    $ cat incorrect.json
    {
      "employeeDetails":{
        "name": "xxxx",
        "num:"415"
      }
      "work":[
      {
        "monthYear":"01/2007"
        "workdate":"1|2|3|....|31",
        "workhours":"8|8|8....|8"
      },
      {
        "monthYear":"02/2007"
        "workdate":"1|2|3|....|31",
        "workhours":"8|8|8....|8"
      }
      ],
    }
    $ cat incorrect.json | jq
    parse error: Expected separator between values at line 4, column 14
    

    修复 JSON 文件后,使用以下技巧加载多行 JSON 文件。

    scala> spark.version
    res5: String = 2.1.1
    
    val employees = spark.read.json(sc.wholeTextFiles("employee.json").values)
    scala> employees.printSchema
    root
     |-- employeeDetails: struct (nullable = true)
     |    |-- name: string (nullable = true)
     |    |-- num: string (nullable = true)
     |-- work: array (nullable = true)
     |    |-- element: struct (containsNull = true)
     |    |    |-- monthYear: string (nullable = true)
     |    |    |-- workdate: string (nullable = true)
     |    |    |-- workhours: string (nullable = true)
    
    scala> employees.select("employeeDetails").show()
    +---------------+
    |employeeDetails|
    +---------------+
    |     [xxxx,415]|
    +---------------+
    

    火花 >= 2.2

    从 Spark 2.2 开始(released quite recently 并强烈推荐使用),您应该改用 multiLine 选项。在SPARK-20980 Rename the option wholeFile to multiLine for JSON and CSV 中添加了multiLine 选项。

    scala> spark.version
    res0: String = 2.2.0
    
    scala> spark.read.option("multiLine", true).json("employee.json").printSchema
    root
     |-- employeeDetails: struct (nullable = true)
     |    |-- name: string (nullable = true)
     |    |-- num: string (nullable = true)
     |-- work: array (nullable = true)
     |    |-- element: struct (containsNull = true)
     |    |    |-- monthYear: string (nullable = true)
     |    |    |-- workdate: string (nullable = true)
     |    |    |-- workhours: string (nullable = true)
    

    【讨论】:

    • 我喜欢这个多行选项。
    • 这些小细节可以让我们的生活变得更轻松(并且值得升级到最新最好的 Spark)。
    • 确实,太糟糕了,云服务商虽然升级需要一些时间
    猜你喜欢
    • 2018-12-30
    • 1970-01-01
    • 2021-03-29
    • 2023-03-19
    • 1970-01-01
    • 2019-09-06
    • 2020-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多