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()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章