如何在Scala DataFrame中为JSON缺失的键填充默认值?
处理Scala中JSON可选字段的读取与默认值设置
在Scala程序中读取JSON数据,需提取
customerid、location、city、state以及嵌套在address键下的status字段。由于status是可选键,部分记录可能不含该字段,直接引用会触发Schema错误,请问如何读取这类缺失键并设置默认值?
示例JSON数据
[ { "customerid": 123, "location": "NA", "address": { "city": "seattle", "state": "washington" } }, { "customerid": 124, "location": "NA", "address": { "city": "seattle", "state": "washington" } } ]
期望输出字段
customerid,location,city,state,status
解决方案(基于Spark SQL)
方法一:显式定义Schema(推荐)
显式定义Schema可避免自动推断的不确定性,明确标记可选字段为可空,读取时不会因缺失字段报错,再通过coalesce设置默认值:
import org.apache.spark.sql.SparkSession import org.apache.spark.sql.types._ import org.apache.spark.sql.functions._ object JsonOptionalFieldHandler { def main(args: Array[String]): Unit = { val spark = SparkSession.builder() .appName("JsonOptionalField") .master("local[*]") .getOrCreate() // 定义包含可选字段的Schema val jsonSchema = StructType(Seq( StructField("customerid", IntegerType, nullable = false), StructField("location", StringType, nullable = false), StructField("address", StructType(Seq( StructField("city", StringType, nullable = false), StructField("state", StringType, nullable = false), StructField("status", StringType, nullable = true) // 标记为可选字段 )), nullable = false) )) // 读取JSON数据(替换为你的文件路径) val rawDf = spark.read.schema(jsonSchema).json("data/customers.json") // 提取目标字段,给缺失的status设置默认值 val resultDf = rawDf.select( $"customerid", $"location", $"address.city", $"address.state", coalesce($"address.status", lit("unknown")).alias("status") ) // 输出结果 resultDf.show() // 若需导出为CSV: // resultDf.write.option("header", "true").csv("output/customers.csv") } }
方法二:自动推断Schema + 条件判断
如果不需要提前定义Schema,可利用Spark自动推断Schema的特性,结合when+otherwise处理缺失值:
import org.apache.spark.sql.SparkSession import org.apache.spark.sql.functions._ object JsonOptionalFieldHandler { def main(args: Array[String]): Unit = { val spark = SparkSession.builder() .appName("JsonOptionalField") .master("local[*]") .getOrCreate() // 自动推断Schema读取JSON val rawDf = spark.read.json("data/customers.json") // 提取字段并处理缺失的status val resultDf = rawDf.select( $"customerid", $"location", $"address.city", $"address.state", when($"address.status".isNotNull, $"address.status") .otherwise("unknown").alias("status") ) resultDf.show() } }
额外处理:若address字段也可能缺失
如果JSON中address本身存在缺失的情况,需要先判断address是否非null,再读取status:
when($"address".isNotNull && $"address.status".isNotNull, $"address.status") .otherwise("unknown").alias("status")
内容的提问来源于stack exchange,提问作者Shankar Panda
相关产品推荐
相关产品推荐

