Scala 开发日志
Spark(使用Scala) Row 转 JSON
将给定Dataframe的Row转为JSON格式
Q:需要将原数据帧A处理成以下数据帧B,其中C列包含原数据的C1,C2,C3列:
原数据帧A:
| A | B | C1 | C2 | C3 |
-------------------------------------------------------------
| 1 | test | ab | 22 | TRUE |
| 2 | mytest | gh | 17 | FALSE |
处理后数据帧B:
| A | B | C |
-------------------------------------------------------------------
| 1 | test | { "c1" : "ab", "c2" : 22, "c3" : TRUE } |
| 2 | mytest | { "c1" : "gh", "c2" : 17, "c3" : FALSE }|
A:代码如下
// 1.添加json4s-native的依赖
import org.json4s._
import org.json4s.jackson.JsonMethods._
// 2.创建一个新的会话
val spark = SparkSession.builder().getOrCreate()
// 3.将数据帧A转为RDD, 再转为map
var dfAtoB= dfA.rdd.map(row => {
val A = row.getAs[String]("A") //获取数据帧A中的A列
val B = row.getAs[String]("B") //获取数据帧A中的B列
val seq: Seq[String] = Seq( "C1","C2","C3") //过滤条件: 过滤一行中需要转为json的列
Row(A, B, convertRowSpecifiedValueToJson(row,seq))
})
// 创建新表包含的列
val structType = StructType(Seq(
StructField("A", DataTypes.StringType, false),
StructField("B", DataTypes.StringType, false),
StructField("C", DataTypes.StringType, false)
))
// 创建数据帧B
var dfB = spark.createDataFrame(dfAtoB,structType)
/**
* 行数据转Json格式
* @param row 行数据
* @param seq 过滤条件: 过滤一行中需要转为json的列
* @return json 字符串
*/
def convertRowSpecifiedValueToJson(row: Row, seq: Seq[String]): String = {
var m: Map[String,Object] = row.getValuesMap(row.schema.fieldNames)
m = m.filter(x => seq.contains(x._1)) //过滤掉seq中不存在的列, 将seq中存在的列放入map中
m = m.map(v => {
// 如果该列的值为null 则将键值映射为 map(key,value) => (列名,"")
if(v._2 == null) (v._1, "") else v //v._1:列名 v._2:列的值
})
compact(render((Extraction.decompose(m)(DefaultFormats)))) // map转row
}
Note: 如果想将整行的数据都转为json,则可以不传入seq过滤列,代码如下
def convertRowValueToJson(row: Row): String = {
var m: Map[String,Object] = row.getValuesMap(row.schema.fieldNames)
m = m.map(v => {
// 如果该列的值为null 则将键值映射为 map(key,value) => (列名,"")
if(v._2 == null) (v._1, "") else v //v._1:列名 v._2:列的值
})
compact(render((Extraction.decompose(m)(DefaultFormats)))) // map转row
}
将整行处理为json 再作为一列返回原数据帧的结果如下所示:
| A | B | C |
-------------------------------------------------------------------------------------------
| 1 | test | { "A" : "1","B" : "test","c1" : "ab", "c2" : 22, "c3" : TRUE } |
| 2 | mytest | { "A" : "2","B" : "mytest", "c1" : "gh", "c2" : 17, "c3" : FALSE }|