Spark SQL中如何将JSON键名转换为对应的值
Spark SQL 动态JSON键值转换方案
你遇到的非规范JSON核心问题是顶级键为包含server标识的动态字符串,Spark读取时会直接把该字符串作为列名,只需提取列名中的server标识,再取出嵌套的x、y字段即可完成转换。
场景1:所有JSON行的顶级键完全相同
如果所有输入JSON行的顶级键统一,直接使用Spark自动推断的列名处理即可,性能最优:
import org.apache.spark.sql.functions._ val cs = spark.read.json("sample.json") // 获取Spark自动推断的顶级列名 val topColName = cs.columns.head val result = cs.select( // 从列名中提取server后的标识 regexp_extract(lit(topColName), "server([A-Za-z0-9]+)", 1).as("server"), // 读取嵌套字段,包含空格的列名需要用反引号包裹 col(s"`${topColName}`.x").as("x"), col(s"`${topColName}`.y").as("y") )
场景2:每行JSON的顶级键不固定(通用方案)
如果不同行的顶级键包含不同的server标识(比如部分行是serverA、部分是serverB),使用兼容度更高的Map解析方案:
import org.apache.spark.sql.functions._ import org.apache.spark.sql.types._ // 先按文本行读取,避免Spark推断出大量零散列 val result = spark.read.text("sample.json") .select( // 将JSON字符串解析为Map结构,key为顶级字符串,value为嵌套结构体 from_json( col("value"), MapType(StringType, StructType(Seq( StructField("x", IntegerType), StructField("y", IntegerType) ))) ).as("json_data") ) // 炸开Map的键值对 .select(explode(col("json_data")).as("top_key", "nested_val")) .select( // 提取server标识 regexp_extract(col("top_key"), "server([A-Za-z0-9]+)", 1).as("server"), // 读取嵌套字段 col("nested_val.x").as("x"), col("nested_val.y").as("y") )
执行result.toJSON.show(false)即可输出你需要的目标结构。
内容的提问来源于stack exchange,提问作者Matthias Gralle
相关产品推荐
相关产品推荐

