Spark SQL 嵌套 JSON 错误“输入时没有可行的替代方案”

Posted

技术标签:

【中文标题】Spark SQL 嵌套 JSON 错误“输入时没有可行的替代方案”【英文标题】:Spark SQL nested JSON error "no viable alternative at input " 【发布时间】:2019-06-01 20:38:53 【问题描述】:

Spark SQL 嵌套 JSON 错误:


  "xxxDetails":  
      "yyyData":  
         "0":  
            "additionalData":  

            ,
            "quantity":80000,
            "www":12.6,
            "ddd":5.0,
            "eee":72000,
            "rrr":false
         ,
         "130":  
            "additionalData":  
               "quantity":1
            ,
            "quantity":0,
            "www":1.0,
            "ddd":0.0,
            "eee":0,
            "rrr":false
         ,
         "yyy":  
            "additionalData":  
               "quantity":1
            ,
            "quantity":0,
            "www":1.0,
            "ddd":0.0,
            "eee":0,
            "rrr":false
                
      
   ,
   "mmmDto":  
      "id":0,
      "name":"",
      "data":null
   
 

当读取 spark.sql("select cast (xxxDetails.yyyData.yyy.additionalData.quantity as Long) as quantity from table") 时,它会起作用,但是: spark.sql("select cast (xxxDetails.yyyData.130. additionalData.quantity as Long) as quantity from table") 将抛出异常:

org.apache.spark.sql.catalyst.parser.ParseException: 在输入'cast(xxxDetails.yyyData.130.

当我为 myDF.select("xxxDetails.yyyData.130.additionalData.quantity") 使用 datafame API 时,它的工作。 任何有体面解释的人:)

【问题讨论】:

【参考方案1】:

这是因为 SQL 列名应以字母或其他字符(如 _@#)开头,但不能以数字开头。让我们考虑这个简单的例子:

Seq((1, 2)).toDF("x", "666").createOrReplaceTempView("test")

调用spark.sql("SELECT x FROM test").show() 会输出

+---+
|  x|
+---+
|  1|
+---+

但调用 spark.sql("SELECT 666 FROM test").show() 代替输出

+---+
|666|
+---+
|666|
+---+

因为666 被解释为文字,而不是列名。要解决此问题,需要使用 backticks 引用列名:

spark.sql("SELECT `666` FROM test").show()
+---+
|666|
+---+
|  2|
+---+

【讨论】:

嗨@ollik1 抱歉,我正在用更多细节更新我的示例/问题,即使我使用该错误仍然存​​在:spark.sql("select cast (xxxDetails.'130'. yyy.quantity as Long) 作为数量。再次对第一个不完整的示例表示抱歉。 这对我有用,@ArnonRodman 请记住它不是单引号而是斜引号,即spark.sql("select cast (xxxDetails.yyyData.`130`.additionalData.quantity as Long) as quantity from table") 编辑答案以强调使用正确的引号字符 Thx @ollik1 和 Richard Nemeth 成功了,我在文档中哪里可以找到它?以及为什么 spark.sql API 与 DataFrame.sql API 不同 不确定是否有比 issues.apache.org/jira/browse/SPARK-3483 更好的文档,这会导致 github.com/apache/spark/pull/2804/files 。它没有解释为什么选择反引号而不是标准 SQL 的双引号。 Dataframe API 有所不同,因为它从方法签名中明确表明传递的字符串引用了一个列。但是,SQL 字符串需要按照一定的规则进行解析和分析。请注意,以数字开头的标识符在 Java、Scala 和 Python 中也会失败

以上是关于Spark SQL 嵌套 JSON 错误“输入时没有可行的替代方案”的主要内容,如果未能解决你的问题,请参考以下文章

在 JAVA 中使用 Spark 2.1.1 读取嵌套 Json(Spark 2.2 有解决方案,但我正在研究 spark 2.1.1 版本)

我如何将平面数据框转换为 spark(scala 或 java)中的嵌套 json

使用 spark 展平嵌套的 json 文档并加载到 Elasticsearch

使用 Spark 从 DynamoDB JSON 字符串中提取嵌套的 Json 字段?

使用 spark 读取和访问 json 文件中的嵌套字段

Spark:如何解析嵌套列表的 JSON 字符串以触发数据框?