在
ETL
中,Spark
经常扮演T
的职务, 也就是进行数据清洗和数据转换.在业务系统中,
JSON
是一个非常常见的数据格式, 在前后端交互的时候也往往会使用JSON
, 所以从业务系统获取的数据很大可能性是使用JSON
格式, 所以就需要Spark
能够支持 JSON 格式文件的读取
读写 JSON
文件
将要 Dataset 保存为 JSON 格式的文件比较简单, 是 DataFrameWriter 的一个常规使用
val spark: SparkSession = new sql.SparkSession.Builder()
.appName("hello")
.master("local[6]")
.getOrCreate()
val dfFromParquet = spark.read.load("dataset/beijing_pm")
// 将 DataFrame 保存为 JSON 格式的文件
dfFromParquet.repartition(1) -----1
.write.format("json")
.save("dataset/beijing_pm_json")
1--> 如果不重新分区, 则会为
DataFrame
底层的RDD
的每个分区生成一个文件, 为了保持只有一个输出文件, 所以重新分区
保存为 JSON 格式的文件有一个细节需要注意, 这个 JSON 格式的文件中,
每一行是一个独立的 JSON, 但是整个文件并不只是一个 JSON 字符串,
所以这种文件格式很多时候被成为 JSON Line 文件, 有时候后缀名也会变为 jsonl
beijing_pm.jsonl
{"day":"1","hour":"0","season":"1","year":2013,"month":3}
{"day":"1","hour":"1","season":"1","year":2013,"month":3}
{"day":"1","hour":"2","season":"1","year":2013,"month":3}
也可以通过 DataFrameReader
读取一个 JSON Line
文件
val spark: SparkSession = ...
val dfFromJSON = spark.read.json("dataset/beijing_pm_json")
dfFromJSON.show()
JSON
格式的文件是有结构信息的, 也就是 JSON
中的字段是有类型的, 例如 "name": "zhangsan"
这样由双引号包裹的 Value
, 就是字符串类型, 而 "age": 10
这种没有双引号包裹的就是数字类型, 当然, 也可以是布尔型 "has_wife": true
Spark
读取 JSON Line
文件的时候, 会自动的推断类型信息
val spark: SparkSession = ...
val dfFromJSON = spark.read.json("dataset/beijing_pm_json")
dfFromJSON.printSchema()
Spark
可以从一个保存了 JSON
格式字符串的 Dataset[String]
中读取 JSON
信息, 转为 DataFrame
这种情况其实还是比较常见的, 例如如下的流程
假设业务系统通过
Kafka
将数据流转进入大数据平台, 这个时候可能需要使用RDD
或者Dataset
来读取其中的内容, 这个时候一条数据就是一个JSON
格式的字符串, 如何将其转为DataFrame
或者Dataset[Object]
这样具有Schema
的数据集呢? 使用如下代码就可以
val spark: SparkSession = ...
import spark.implicits._
val peopleDataset = spark.createDataset(
"""{"name":"Yin","address":{"city":"Columbus","state":"Ohio"}}""" :: Nil)
spark.read.json(peopleDataset).show()
总结
1. JSON
通常用于系统间的交互,Spark
经常要读取JSON
格式文件, 处理, 放在另外一处2. 使用
DataFrameReader
和DataFrameWriter
可以轻易的读取和写入JSON
, 并且会自动处理数据类型信息