【问题标题】:Spark - read JSON array from columnSpark - 从列中读取 JSON 数组
【发布时间】:2021-05-27 21:57:02
【问题描述】:

使用 Spark 2.11,我有以下数据集(从 Cassandra 表中读取):

+------------+----------------------------------------------------------+
|id         |attributes                                                 |
+------------+----------------------------------------------------------+
|YH8B135U123|[{"id":1,"name":"function","score":10.0,"snippets":1}]     |
+------------+----------------------------------------------------------+

这是 printSchema():

root
 |-- id: string (nullable = true)
 |-- attributes: string (nullable = true)

attributes 列是 JSON 对象数组。我正在尝试将其分解为数据集,但一直失败。我试图将架构定义如下:

StructType type = new StructType()
                .add("id", new IntegerType(), false)
                .add("name", new StringType(), false)
                .add("score", new FloatType(), false)
                .add("snippets", new IntegerType(), false );
        
ArrayType schema = new ArrayType(type, false);

并将其提供给from_json,如下所示:

df = df.withColumn("val", functions.from_json(df.col("attributes"), schema));

这会因 MatchError 失败:

Exception in thread "main" scala.MatchError: org.apache.spark.sql.types.IntegerType@43756cb (of class org.apache.spark.sql.types.IntegerType)

这样做的正确方法是什么?

【问题讨论】:

    标签: java json apache-spark apache-spark-sql


    【解决方案1】:

    您可以通过这种方式指定架构:

    val schema = ArrayType(
      StructType(Array(
        StructField("id", IntegerType, false),
        StructField("name", StringType, false),
        StructField("score", FloatType, false),
        StructField("snippets", IntegerType, false)
      )),
      false
    )
    
    val df1 = df.withColumn("val", from_json(col("attributes"), schema))
    
    df1.show(false)
    
    //+-----------+------------------------------------------------------+------------------------+
    //|id         |attributes                                            |val                     |
    //+-----------+------------------------------------------------------+------------------------+
    //|YH8B135U123|[{"id":1,"name":"function","score":10.0,"snippets":1}]|[[1, function, 10.0, 1]]|
    //+-----------+------------------------------------------------------+------------------------+
    

    或者对于 Java:

    import static org.apache.spark.sql.types.DataTypes.*;
    
    
    StructType schema = createArrayType(createStructType(Arrays.asList(
        createStructField("id", IntegerType, false),
        createStructField("name", StringType, false),
        createStructField("score", FloatType, false),
        createStructField("snippets", StringType, false)
    )), false);
    

    【讨论】:

      【解决方案2】:

      您可以将架构定义为文字字符串:

      val df2 = df.withColumn(
          "val",
          from_json(
              df.col("attributes"),
              lit("array<struct<id: int, name: string, score: float, snippets: int>>")
          )
      )
      
      df2.show(false)
      +-----------+------------------------------------------------------+------------------------+
      |id         |attributes                                            |val                     |
      +-----------+------------------------------------------------------+------------------------+
      |YH8B135U123|[{"id":1,"name":"function","score":10.0,"snippets":1}]|[[1, function, 10.0, 1]]|
      +-----------+------------------------------------------------------+------------------------+
      

      如果您更喜欢使用架构:

      val spark_struct = new StructType()
                      .add("id", IntegerType, false)
                      .add("name", StringType, false)
                      .add("score", FloatType, false)
                      .add("snippets", IntegerType, false)
      
      val schema = new ArrayType(spark_struct, false)
      
      val df2 = df.withColumn(
          "val",
          from_json(
              df.col("attributes"),
              schema
          )
      )
      

      您的原始代码存在两个问题:(1) 您使用保留关键字 type 作为变量名,以及 (2) 您不需要在 add 中使用 new

      【讨论】:

      • 这不会为我编译,因为 from_json 期望第二个参数是 DataType 而不是 Column.. 我使用的是 2.11
      • @Seffy 然后试试第二种方法?
      • 试过了,同样的错误。你是什么意思不需要使用“新”?我的编码是 Java,而不是 Scala..
      • 对不起,我误会了...this answer 可能对 java 有帮助
      • 现在也不例外,但是 from_json 永远挂起。数据集只包含 1 行,如何检查那里发生了什么?与本地一起运行。
      猜你喜欢
      • 2018-10-05
      • 2021-06-22
      • 2017-06-28
      • 1970-01-01
      • 2022-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-18
      相关资源
      最近更新 更多