You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Databricks Spark(Scala)读取多行JSON带Schema返回全Null行问题

问题分析与解决方法

你遇到的问题核心是Schema中time字段的类型与JSON中的数据格式不匹配,结合multiLine选项的特性,导致Spark解析失败,最终返回全Null的记录。

具体原因

JSON里的time字段是纯时间字符串(如"17:05:23"),但你在Schema中定义为TimestampType。Spark默认的Timestamp解析规则要求字符串包含日期+时间的完整格式(比如yyyy-MM-dd HH:mm:ss),纯时间字符串无法被解析为Timestamp;而Spark默认开启容错模式(mode="PERMISSIVE"),会把解析失败的整条记录置为Null。

至于不指定Schema时能正常读取,是因为Spark自动推断类型时会把time识别为StringType,避开了解析失败的问题。


解决方案

方案1:修改Schema中time字段为StringType

直接将time字段类型改为字符串,后续可根据需求再转换为时间类型:

val pitStopsSchema = StructType(Array(
    StructField("driverId", IntegerType, true),
    StructField("duration", DoubleType, true),
    StructField("lap", IntegerType, true),
    StructField("milliseconds", LongType, true),
    StructField("raceId", IntegerType, true),
    StructField("stop", IntegerType, true),
    StructField("time", StringType, true) // 改为StringType
  ))

var df = spark.read.schema(pitStopsSchema)
               .option("multiLine", true)
               .json("dbfs:/mnt/kchirchir/formulaone/raw/pit_stops.json")

方案2:指定Timestamp解析格式适配纯时间字符串

如果需要保留TimestampType,可以通过timestampFormat选项指定时间字符串格式,让Spark正确解析:

val pitStopsSchema = StructType(Array(
    StructField("driverId", IntegerType, true),
    StructField("duration", DoubleType, true),
    StructField("lap", IntegerType, true),
    StructField("milliseconds", LongType, true),
    StructField("raceId", IntegerType, true),
    StructField("stop", IntegerType, true),
    StructField("time", TimestampType, true)
  ))

var df = spark.read.schema(pitStopsSchema)
               .option("multiLine", true)
               .option("timestampFormat", "HH:mm:ss") // 指定纯时间格式
               .json("dbfs:/mnt/kchirchir/formulaone/raw/pit_stops.json")

方案3:改用TimeType类型(Spark 3.0+支持)

如果只需要存储时间信息、不需要日期,可以使用TimeType替代TimestampType,它专门处理HH:mm:ss格式的纯时间字符串:

import org.apache.spark.sql.types.TimeType

val pitStopsSchema = StructType(Array(
    StructField("driverId", IntegerType, true),
    StructField("duration", DoubleType, true),
    StructField("lap", IntegerType, true),
    StructField("milliseconds", LongType, true),
    StructField("raceId", IntegerType, true),
    StructField("stop", IntegerType, true),
    StructField("time", TimeType, true) // 使用TimeType
  ))

var df = spark.read.schema(pitStopsSchema)
               .option("multiLine", true)
               .json("dbfs:/mnt/kchirchir/formulaone/raw/pit_stops.json")

额外检查点

确认你的JSON文件整体结构是否为数组包裹(比如[ {...}, {...} ])。如果文件只是多个独立JSON对象用逗号分隔而没有外层数组,虽然multiLine=true能让Spark读取,但结合Schema解析时可能出现隐性不匹配。不过从你不指定Schema能正常读取的情况来看,这个问题影响较小,核心还是time字段的类型匹配问题。

内容的提问来源于stack exchange,提问作者Kenneth Chirchir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:31:03