天天看点

Spark SQL读取JSON案例以及存在的坑

Spark可以读取JSON,将其转换为DataFrame ( DataFrame[Row] )

Spark SQL可以自动推断JSON的schema,但是如果显式的提供模式可以避免额外的扫描

需要注意是:如果是读取JSON文件,提供的json文件不是典型的JSON文件,而是每行属于合法的JSON,然后用分隔符分割,具体规则:http://jsonlines.org/

官网Demo地址:http://spark.apache.org/docs/latest/sql-data-sources-json.html

读取JSON文件

// 以下是测试文件的json
//{"id": 1, "name": "mwf", "age": 23}
//{"id": 2, "name": "zqr", "age": 23}

val structType = new StructType()
    .add("id", IntegerType)
    .add("name", StringType)
    .add("age", IntegerType)

//读json文件,读取的时候也可以不指定schema,spark可以自动推断类型
val jsonDF = spark
   .read
   .schema(structType)
   .json("D:\\learning_spark\\spark_demo\\src\\main\\resources\\read_json.jsonl")

jsonDF.printSchema()
jsonDF.show()
           

读取JSON String

val seq = Seq("{\"id\": 1, \"name\": \"mwf\", \"age\": 23}", 
			  "{\"id\": 2, \"name\": \"zqr\", \"age\": 23}")

val jsonStringRdd = spark
    .sparkContext
    .parallelize(seq)

import spark.implicits._
// 也可以直接创建DS spark.createDataset(seq)
val jsonDS= jsonStringRdd.toDS()

//也可以直接传jsonStringRdd, 不过spark建议我们传入DataSet
val jsonDF2 = spark
    .read
    .json(jsonDS)
jsonDF2.show()
           

读取JSON的时候,存在的坑

当不指定schema时,可以读到正确的JSON;但是当指定schema后,读取到的JSON值都为null
{"id": "1", "name": "mwf", "age": 23}
{"id": "2", "name": "zqr", "age": 23}
           

以上JSON,我们如果指定如下schema:

val structType = new StructType()
    .add("id", IntegerType)
    .add("name", StringType)
    .add("age", IntegerType)
           

读取出来就会 每行都变为null

将注意力放到"id":"1"那里,1是加了引号的,意味着他是一个字符串,而不是int类型的

spark无法直接从String转换为Integer,会将整行记录置为null

要解决如上问题,我们可以将id变为int值;或者直接将schema的类型都指定为String,在读取进来以后再处理为想要的类型

以下两个网站解决了我的疑问,大家也可以直接点过去看

https://codeday.me/bug/20190406/896703.html

https://blog.antlypls.com/blog/2016/01/30/processing-json-data-with-sparksql

居安思危,跳出安逸!

继续阅读