Spark系列 —— 將JSON數據轉化爲Dataset/DataFrame

JSON轉DataFrame

 
在日常使用Spark處理數據時, 半結構化的JSON數據(JSONObject, JSONArray)可能是最常見的一種數據結構,那麼能熟練並快速地處理JSON格式數據應該是數據開發人員的必備技能。

接下來我們就看看該如何將各種格式的JSON數據轉成DataFrame。
 

1. 讀取JSON文件

讀取指定路徑下的json文件(或者存放json文件的目錄),加載爲DataFrame。
 

本地文件
	//本地路徑
	val path = "file:/opt/package/jar/bank_statement_detail.json"
	spark.read.json(path).show()
HDFS文件
	//HDFS路徑
	val path = "/file/bank_statement_detail.json"
	spark.read.json(path).show()

 

2. List、Seq

將一個List或Seq加載爲DataFrame。

	import spark.implicits._
	val ds = spark.createDataset("""[{"name": "Spark", "age": 10}, {"name": "Flink", "age": 5}]""" :: Nil)
	spark.read
		//默認的timestampFormat爲 yyyy-MM-dd'T'HH:mm:ss.SSSXXX, SSS爲毫秒數, XXX爲非法字符(會報錯"java.lang.IllegalArgumentException: Illegal pattern component: XXX"),
		//需要手動設置時區爲Z(即UTC時間)
		.option("timestampFormat", "yyyy/MM/dd HH:mm:ss.SSSZ")
		.json(ds)
		.show()

 

3. JSON String類型的Column

JSON String類型的Column, 拿Hive來舉例的話,就是Hive表中的某一列,其類型爲String,其值是JSONArray類型("[{‘name’: ‘Spark’, ‘age’: 10}, {‘name’: ‘Flink’, ‘age’: 5}]"),或者是JSONObject類型("{‘name’: ‘Spark’, ‘age’: 10}")。
 
這種情況可以用以下兩種方式處理:

方式一(map函數處理)
	import com.alibaba.fastjson.JSON

	import spark.implicits._
	
	//person_info爲string類型的JSONArray("[{'name': 'Spark', 'age': 10}, {'name': 'Flink', 'age': 5}]")
	val df = spark.read.table("db_name.table_name").select("person_info")
	
	//JSON string類型的Dataset轉成DataFrame
	val ds = df.map(row => JSON.parseArray(row.toString).get(0).toString) 
	
	ds.show()

 

方式二(指定schema)
	import org.apache.spark.sql.types._

	import spark.implicits._
	
	//person_info爲string類型的JSONArray("[{'name': 'Spark', 'age': 10}, {'name': 'Flink', 'age': 5}]")
	val df = spark.read.table("db_name.table_name").select("person_info")
	
	val schema = ArrayType(StructType(StructField("name", StringType):: StructField("age", IntegerType)::Nil))
	
	val resultDF = df.select(from_json($"person_info", schema).as("info")) //將JSONArray列映射到一個schema上
		.select(explode($"info").as("info")) //展開JSONArray中的元素(JSONObject)爲多行
		.select("info.name", "info.age") //獲取每個JSONObject中每個key對應的value
	
	resultDF.show()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章