Spark报错scala.collection.immutable.$colon$colon非string schema合法类型的原因与修复
问题根因
- 核心错误是Row构造方式不对:Spark的
Row构造默认接收可变参数,你直接传入整个List[AnyRef]对象,相当于构造出来的Row只有1个字段,值就是这个List本身(scala不可变List的实现类就是报错信息里的scala.collection.immutable.$colon$colon),但你定义的Schema第一个字段是StringType,类型完全不匹配,触发报错。 - 次要隐患:Schema定义存在重复字段名,
array_int和array_string各出现了两次,Spark DataFrame不允许同层级字段重名,即使类型匹配后续也会报错。
修复步骤
- 替换Row构造方法:把
Row(getList)改为Row.fromSeq(getList),fromSeq会自动把List里的每个元素按顺序展开为Row的对应字段,和Schema的字段顺序一一匹配。 - 修正Schema的重复字段名,把后两个重名字段改为业务对应的唯一名称即可。
修复后核心代码示例
// 修正重名字段后的Schema val schema = StructType(Seq( StructField("string", StringType), StructField("int", IntegerType), StructField("decimal", DecimalType(10, 2)), StructField("timestamp", TimestampType), StructField("array_string", ArrayType(StringType)), StructField("array_int", ArrayType(IntegerType)), StructField("array_decimal", ArrayType(DecimalType(10, 2))), StructField("array_timestamp", ArrayType(TimestampType)), StructField("array_int_null", ArrayType(IntegerType)), StructField("array_string_null", ArrayType(StringType)) )) val encoder = RowEncoder(schema) import spark.implicits._ List((1, 2, 3, 4)) .toDF("f1", "f2", "f3", "f4") .as[Rec] .map(rec => { // 用fromSeq展开List元素作为Row的字段 Row.fromSeq(getList) })(encoder) .show()
额外注意
生产环境需要保证getList返回的List长度、每个位置的元素类型,和Schema定义的字段数量、字段类型完全对齐,否则仍会出现类型不匹配或者索引越界错误。
内容的提问来源于stack exchange,提问作者J.J. Kubrick
相关产品推荐
相关产品推荐

