如何解析具有嵌套模式的json?

时间:2019-05-03 16:58:31

标签: json scala apache-spark databricks jsonparser

让我的json的架构为:

       root
     |-- data: array (nullable = true)
     |    |-- element: array (containsNull = true)
     |    |    |-- element: string (containsNull = true)

JSON就是这样

{
  "data": [
    [
      10429183,
      "4057F5BE-1933-415E-9AF7-D3CAAC5ED8E6",
      10429183,
      1454527245,
      "386824",
      1454527245,
      "386824",
      null,
      "6702002",
      "HM193685",
      "2006-02-21T21:00:00",
      "078XX S VERNON AVE",
      "2092",
      "NARCOTICS",
      "SOLICIT NARCOTICS ON PUBLICWAY",
      "STREET",
      true,
      false,
      "0624",
      "006",
      "6",
      "69",
      "26",
      null,
      null,
      "2006",
      "2015-08-17T15:03:40",
      null,
      null,
      [
        null,
        null,
        null,
        null,
        null
      ]
    ]
  ]
}
val df2 = 
df1
.withColumn("data", explode(array(jsonElements: _*)))
.withColumn("id", $"data" (0)).select("data.*") 

错误:

  

线程“ main”中的异常org.apache.spark.sql.AnalysisException:可以   仅星形扩展结构数据类型。属性:ArrayBuffer(data);

是否需要为每个数据元素创建一个数据框?

2 个答案:

答案 0 :(得分:2)

据我了解,您正在尝试将数组中的每个json元素拆分为单独的列...

一种方法如下

import org.apache.spark.sql._

object JsonTest extends App {
  val jsonStr =
    """
      |{
      |  "data": [
      |    [
      |      10429183,
      |      "4057F5BE-1933-415E-9AF7-D3CAAC5ED8E6",
      |      10429183,
      |      1454527245,
      |      "386824",
      |      1454527245,
      |      "386824",
      |      null,
      |      "6702002",
      |      "HM193685",
      |      "2006-02-21T21:00:00",
      |      "078XX S VERNON AVE",
      |      "2092",
      |      "NARCOTICS",
      |      "SOLICIT NARCOTICS ON PUBLICWAY",
      |      "STREET",
      |      true,
      |      false,
      |      "0624",
      |      "006",
      |      "6",
      |      "69",
      |      "26",
      |      null,
      |      null,
      |      "2006",
      |      "2015-08-17T15:03:40",
      |      null,
      |      null,
      |      [
      |        null,
      |        null,
      |        null,
      |        null,
      |        null
      |      ]
      |    ]
      |  ]
      |}
    """.stripMargin
  private[this] implicit val spark = SparkSession.builder().master("local[*]").getOrCreate()

  spark.sparkContext.setLogLevel("ERROR")

  import org.apache.spark.sql.functions._
  import spark.implicits._

  val df1 = spark.read.json(Seq(jsonStr).toDS)
  println("before explode")
  df1.show(false)
  println(df1.schema)
  println("after explode")
  //  import org.apache.spark.sql.functions.schema_of_json
  //  val schema = df1.select(schema_of_json($"data")).as[String].first
  //  df1.withColumn("jsonData", from_json($"data", schema, Map[String, String]())).show
  val df2 = df1
    .withColumn("data", explode(col("data")))
  println(df2.schema)
  df2.show(false)

  val nElements = 35
  df2.select(Range(0, nElements).map(idx => $"data" (idx) as "data" + (idx + 2)): _*).show(false)

}

结果:

before explode
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|data                                                                                                                                                                                                                                                                                                                    |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|[[10429183, 4057F5BE-1933-415E-9AF7-D3CAAC5ED8E6, 10429183, 1454527245, 386824, 1454527245, 386824,, 6702002, HM193685, 2006-02-21T21:00:00, 078XX S VERNON AVE, 2092, NARCOTICS, SOLICIT NARCOTICS ON PUBLICWAY, STREET, true, false, 0624, 006, 6, 69, 26,,, 2006, 2015-08-17T15:03:40,,, [null,null,null,null,null]]]|
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

StructType(StructField(data,ArrayType(ArrayType(StringType,true),true),true))
after explode
StructType(StructField(data,ArrayType(StringType,true),true))
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|data                                                                                                                                                                                                                                                                                                                  |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|[10429183, 4057F5BE-1933-415E-9AF7-D3CAAC5ED8E6, 10429183, 1454527245, 386824, 1454527245, 386824,, 6702002, HM193685, 2006-02-21T21:00:00, 078XX S VERNON AVE, 2092, NARCOTICS, SOLICIT NARCOTICS ON PUBLICWAY, STREET, true, false, 0624, 006, 6, 69, 26,,, 2006, 2015-08-17T15:03:40,,, [null,null,null,null,null]]|
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

+--------+------------------------------------+--------+----------+------+----------+------+-----+-------+--------+-------------------+------------------+------+---------+------------------------------+------+------+------+------+------+------+------+------+------+------+------+-------------------+------+------+--------------------------+------+------+------+------+------+
|data2   |data3                               |data4   |data5     |data6 |data7     |data8 |data9|data10 |data11  |data12             |data13            |data14|data15   |data16                        |data17|data18|data19|data20|data21|data22|data23|data24|data25|data26|data27|data28             |data29|data30|data31                    |data32|data33|data34|data35|data36|
+--------+------------------------------------+--------+----------+------+----------+------+-----+-------+--------+-------------------+------------------+------+---------+------------------------------+------+------+------+------+------+------+------+------+------+------+------+-------------------+------+------+--------------------------+------+------+------+------+------+
|10429183|4057F5BE-1933-415E-9AF7-D3CAAC5ED8E6|10429183|1454527245|386824|1454527245|386824|null |6702002|HM193685|2006-02-21T21:00:00|078XX S VERNON AVE|2092  |NARCOTICS|SOLICIT NARCOTICS ON PUBLICWAY|STREET|true  |false |0624  |006   |6     |69    |26    |null  |null  |2006  |2015-08-17T15:03:40|null  |null  |[null,null,null,null,null]|null  |null  |null  |null  |null  |
+--------+------------------------------------+--------+----------+------+----------+------+-----+-------+--------+-------------------+------------------+------+---------+------------------------------+------+------+------+------+------+------+------+------+------+------+------+-------------------+------+------+--------------------------+------+------+------+------+------+

您可以使用withColumn更改列名称,还可以删除不需要的列。.

答案 1 :(得分:1)

如果我的理解正确,您正在尝试将外部阵列爆炸到新列data中。然后,将该数组的第一个值放入新字段id中。如果是这种情况,那么下一个代码应该可以帮助您:

df.withColumn("data", explode($"data"))
  .withColumn("id", $"data".getItem(0))
  .show()

输出:

+--------------------+--------+
|                data|      id|
+--------------------+--------+
|[10429183, 4057F5...|10429183|
+--------------------+--------+