在
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
, 並且會自動處理數據類型信息