如何将带有nullable = false的模式应用于json读取

时间:2017-11-22 20:36:02

标签: apache-spark

我试图使用json文件为数据帧编写一些测试用例(而生产将是镶木地板)。我使用基于spark测试的框架,并且当由于模式不匹配而断言数据帧彼此相等时我遇到了麻烦,其中json模式总是具有nullable = true。

我希望能够将带有nullable = false的模式应用于json读取。

我写了一个小测试用例:

import com.holdenkarau.spark.testing.DataFrameSuiteBase
import org.apache.spark.sql.types.{IntegerType, StructField, StructType}
import org.scalatest.FunSuite

class TestJSON extends FunSuite with DataFrameSuiteBase {

  val expectedSchema = StructType(
    List(StructField("a", IntegerType, nullable = false),
         StructField("b", IntegerType, nullable = true))
  )
  test("testJSON") {
    val readJson =
      spark.read.schema(expectedSchema).json("src/test/resources/test.json")

    assert(readJson.schema == expectedSchema)

  }
}

并有一个小的test.json文件: {"a": 1, "b": 2} {"a": 1}

这会返回

的断言失败
  

StructType(StructField(一,IntegerType,真),   StructField(b,IntegerType,true))不相等   StructType(StructField(A,IntegerType,假的),   StructField(b,IntegerType,true))ScalaTestFailureLocation:   TestJSON $$ anonfun $ 1 at(TestJSON.scala:15)预期   :StructType(StructField(一,IntegerType,假),   StructField(b,IntegerType,true))实际
  :StructType(StructField(A,IntegerType,真)   StructField(B,IntegerType,真))

我是否以正确的方式应用架构? 我使用spark 2.2,scala 2.11.8

2 个答案:

答案 0 :(得分:3)

有一种解决方法,不是直接从文件中读取json,而是使用RDD读取它,然后应用模式。以下是代码:

val expectedSchema = StructType(
    List(StructField("a", IntegerType, nullable = false),
         StructField("b", IntegerType, nullable = true))
  )


  test("testJSON") {
    val jsonRdd =spark.sparkContext.textFile("src/test/resources/test.json")
    //val readJson =sparksession.read.schema(expectedSchema).json("src/test/resources/test.json")
    val readJson = spark.read.schema(expectedSchema).json(jsonRdd)
    readJson.printSchema()
    assert(readJson.schema == expectedSchema)

  }

测试用例通过,打印模式结果为:

root
 |-- a: integer (nullable = false)
 |-- b: integer (nullable = true)

对于这个问题,有一个带有apache Spark的JIRA https://issues.apache.org/jira/browse/SPARK-10848,他们说这不是问题,并说:

  

这应该在Spark 2.0中的最新文件格式重构中解决。如果你仍然遇到问题,请重新打开它。谢谢!

如果您收到错误,可以再次打开JIRA。 我在spark 2.1.0中测试过,仍然看到同样的问题

答案 1 :(得分:0)

上面的workAround确保存在正确的模式,但是将null值设置为默认值。在我的情况下,当json String中不存在Int时,它被设置为0。