PySpark from_json报错:无法解析JSON schema 未识别array标记
故障原因
两个核心问题导致报错:
- 写入Parquet时的类型转换逻辑错了:你用
cast('string')把array<struct>类型转字符串,得到的是Spark内部的对象字符串表示,不是标准JSON。你自己看查询输出的内容[{f1a, f2a}, {f1b, f2b}],这里面连结构体的字段名都没保留,就算开了allowUnquotedFieldNames配置也不可能解析成功——这个配置只允许JSON字段名不加双引号,不接受字段名直接缺失的非法格式。 - 解析时传的schema存在两个小问题:一是你代码里写的schema把尖括号转义成了HTML实体
</>,Spark识别不了;二是你的字段名带横杠array-field-1,在DDL schema里需要用反引号包裹,不然会被解析成减法表达式。
解决方案
分两种场景处理:
可重跑Parquet写入流程
这是最稳妥的方案,把写入时的类型转换逻辑改掉,不要直接cast成string,用官方的to_json函数生成标准JSON字符串:
from pyspark.sql.functions import col, to_json parquet_path = "/tmp/test-parquet" df = spark.read.json('t2.json') # 替换cast('string')为to_json,输出标准JSON格式 df = df.withColumn('some-array', to_json(col('some-array'))) df.write.mode("overwrite").parquet(parquet_path)
后续读取解析的时候,传入正确格式的DDL schema即可:
from pyspark.sql.functions import from_json final_df = spark.read.parquet(parquet_path) # 注意带横杠的字段用反引号包裹,尖括号用原生<> parse_schema = 'array<struct<`array-field-1`:string, `array-field-2`:string>>' final_df.select( from_json(col('some-array'), parse_schema).alias('json1') ).show(2, False)
执行后就能正常解析出结构体数组。
已经生成Parquet、无法重跑写入
你现在存下来的字符串虽然不是JSON,但保留了结构体值的顺序,不需要走JSON解析流程,直接强转回对应类型即可:
from pyspark.sql.types import * from pyspark.sql.functions import col final_df = spark.read.parquet(parquet_path) # 定义和原始数据一致的schema target_schema = ArrayType(StructType([ StructField("array-field-1", StringType()), StructField("array-field-2", StringType()) ])) # 直接cast回目标类型,比JSON解析性能更高 final_df.select( col('some-array').cast(target_schema).alias('parsed_col') ).show(2, False)
这种方式不用额外处理字符串,性能比正则拼接JSON再解析高很多。
避坑提示
- 所有复杂类型(数组、结构体、Map)转JSON字符串统一用
to_json函数,不要直接cast('string'),后者输出的是调试用的内部字符串格式,不保证跨Spark版本兼容,也不符合JSON规范。 - DDL格式的schema中,带特殊字符(横杠、空格、SQL关键字)的字段名必须用反引号包裹,否则会解析失败。
- 代码里写schema直接用原生尖括号
<>,不要复制网页内容里转义后的</>实体字符。
内容的提问来源于stack exchange,提问作者Usergtwuser
相关产品推荐
相关产品推荐

