【Spark】解析JSON格式HDFS大文件实践

本文介绍了如何使用Spark从HDFS读取JSON格式的大文件,并通过分区处理成RDD[Row],再转换为DataFrame以便进行SparkSQL操作。详细步骤包括读取HDFS目录、解析JSON字符串和转换DataFrame。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、读取HDFS目录并分区

  • 其中validPath为目标文件所在的目录,默认读取目录下全部文件,指定读取到RDD后,分区数为8。
  • mapPartitions为以某一个分区为单位,对该单位内的每一行做操作。
  • iter为RDD分区后的每个分区数据的基本操作遍历器,类型为Iterator
val jsonRdd = CommonHelper.getSparkContext().textFile(validPath.toString, 8)
val result = jsonRdd.mapPartitions(iter => parseJsonStr(iter))
//取RDD前十条数据进行打印
result.take(10).foreach {
  println
}

二、将HDFS每一行JSON字符串按分区处理成RDD[Row]

  • 创建Row类型对应的Schema
val schema = StructType(List(
  StructField("id", ArrayType(LongType, true), true),
  StructField("fea", ArrayType(StringType, true), true),
  StructField("width", IntegerType, true),
  StructField("height", IntegerType, true),
  StructField("date", StringType, true),
  StructField("format_type", StringType, true),
  StructField("source", StringType, true)
))
  • parseJsonStr方法如下
def parseJsonStr(iter: Iterator[String]): Iterator[Row] = {
    var list = ArrayBuffer[Row]()
    while (iter.hasNext) {
      var array = new ArrayBuffer[Any]()
      val json: JSONObject = JSON.parseObject(iter.next())
      val adIds = json.getJSONArray("ids").toArray
      var adIdsList: scala.List[Long] = List()
      for (id <- adIds) {
        adIdsList = adIdsList.::(id.asInstanceOf[Number].longValue)
      }
      array += adIdsList.toArray
      val feas = json.getJSONArray("fea").toArray
      array += feas
      val width = json.getIntValue("width")
      array += width
      val height = json.getIntValue("height")
      array += height
      val date = json.getString("date")
      array += date
      val typeStr = json.getString("type")
      array += typeStr
      val source = json.getString("source")
      array += source
      var row = new GenericRowWithSchema(array.toArray, schema)
      list += (row)
    }
    list.toList.iterator
  }

三、将RDD[Row]转换成DataFrame

  • 转换后方便执行SparkSQL,而RDD不支持SparkSQL
  • 按照同样一套schema转换即可
al df3 = spark.createDataFrame(result, schema)
println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date) + ":track DataFrame:" + dfName + ",count:" + df3.count())
    df3.printSchema()
    df3.show()

四、总结

  • mapPartitions相较于map算子有更大的计算优势,内部函数执行次数前者为分区数,后者为总行数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值