为什么 schema_of_json 失败?

MrE*_*ant 1 apache-spark

为什么第二次转型失败了?

\n
df\n  .withColumn("schemaDetected", schema_of_json(lit("""{"Zipcode":704,"ZipCodeType":"STANDARD","City":"PARC PARQUE","State":"PR"}""")))\n  .show(false)\n//shows: struct<City:string,State:string,ZipCodeType:string,Zipcode:bigint>\n\ndf\n  .withColumn("literal", lit("""{"Zipcode":704,"ZipCodeType":"STANDARD","City":"PARC PARQUE","State":"PR"}"""))\n  .withColumn("schemaDetected", schema_of_json(col("literal")))\n  .show(false)\n// it fails:\n// cannot resolve 'schema_of_json(`literal`)' due to data type mismatch: The input json should be a string literal and not null; however, got `literal`.;;\n
Run Code Online (Sandbox Code Playgroud)\n

我需要获取一个列模式,但它只接受方法内部包含的“lit”,当我添加列时它会失败。\xc2\xbf为什么?

\n

Vin*_*oba 5

第二个转换失败,因为当您将包含 json 字符串的列从数据帧传递到schema_of_json函数 Spark 时,无法确定该列的每一行 json 字符串将计算为相同的架构

要理解为什么所有行具有相同的架构很重要,您必须承认创建schema_of_json函数的主要用例是推断from_json函数的架构。

from_json将 json 字符串转换为struct,基本上是几个新列。当然,数据框中的所有行都应该具有相同的列。因此,您必须确保from_json在数据帧上使用时,将相同的架构传递给所有行。

在原点,您应该能够传递不是literalto的列,如您在票证SPARK-24642schema_of_json中看到的那样。然而,这意味着合并每一行的推断模式。例如,如果您有以下数据框:

+------------------+
| json_string      |
+------------------+
| {"a": 1}         |
| {"b": 2}         |
| {"a": 3, "c": 4} |
+------------------+
Run Code Online (Sandbox Code Playgroud)

并且您想要将返回的模式传递给schema_of_json函数from_json,您必须推断模式STRUCT<a INT, b INT, c INT>才能为所有行提供一致的模式。为此,您需要转换schema_of_json为聚合函数,该函数将通过迭代参数列的所有值来构建架构或进行架构推断(就像读取 CSV 时一样)。被认为不值得

因此,您不能传递数据帧列作为参数,而只能传递literal,您可以使用SPARK-24709lit中实现的函数来获取它

schema_of_json后来在 Spark 3.1 中进行了升级(请参阅SPARK-31044),以便能够采用可折叠列,这意味着可以在查询执行之前静态评估列。这种可折叠柱的一个例子是regexp_replace(lit("""{"test":1}""", "1", "2")),它不是直接的,literal而是一个literal

因此,回到您的案例,当您从 中创建列时lit(...),Spark 会看到该列,但看不到其内容。由于 Spark 看不到列的内容,因此无法确定该列的值是否相同。但 Spark 必须确保这些值生成的模式相同,因此它必须确保输入值相同。所以它会抛出一个错误,基本上说“我不能确定对于所有行,此列中包含的 json 字符串都是相同的”