【问题标题】:Processing json strings in a Spark dataframe column处理 Spark 数据框列中的 json 字符串
【发布时间】:2017-05-25 20:16:14
【问题描述】:

当我寻找在数据框的字符串列中解析 json 的方法时,我不断遇到更简单地读取 json 文件源的结果。我的源实际上是一个配置单元 ORC 表,其中一个列中有一些字符串,它是 json 格式。我真的很想把它转换成像地图一样解析的东西。

我很难找到一种方法来做到这一点:

import java.util.Date
import org.apache.spark.sql.Row
import scala.util.parsing.json.JSON

val items = sql("select * from db.items limit 10")
//items.printSchema
val internal = items.map {
  case Row(externalid: Long, itemid: Long, locale: String,
           internalitem: String, version: Long,
           createdat: Date, modifiedat: Date)
       => JSON.parseFull(internalitem)
}

我认为这应该可行,但也许有一种更 Spark 的方式来代替,因为我收到以下错误:

java.lang.ClassNotFoundException: scala.Any
 at scala.reflect.internal.util.AbstractFileClassLoader.findClass(AbstractFileClassLoader.scala:62)

具体来说,我的输入数据大概是这样的:

externalid, itemid, locale, internalitem, version, createdat, modifiedat
       123,    321, "en_us", "{'name':'thing','attr':{
                               21:{'attrname':'size','attrval':'big'},
                               42:{'attrname':'color','attrval':'red'}
                              }}",              1, 2017-05-05…, 2017-05-06…

是的,它不完全是 RFC 7158。

attr 键可以是任何 80,000 个值中的 5 到 30 个,所以我想改为这样:

externalid, itemid, locale, internalitem, version, createdat, modifiedat
       123,    321, "en_us", "{"name':"thing","attr":[
                               {"id":21,"attrname':"size","attrval":"big"},
                               {"id":42,"attrname":"color","attrval":"red"}
                              ]}",              1, 2017-05-05…, 2017-05-06…

然后将internalitem 展平为字段并分解attr 数组:

externalid, itemid, locale, name, attrid, attrname attrval, version, createdat, modifiedat
       123,    321, "en_us", "thing", 21,   "size",  "big",       1, 2017-05-05…, 2017-05-06…
       123,    321, "en_us", "thing", 21,  "color",  "red",       1, 2017-05-05…, 2017-05-06…

【问题讨论】:

  • 此代码通过解析源数据帧中的数据字段来创建一个新数据帧。 spark.sqlContext.read.json(df.select("col1").rdd.map(_.getAs[String](0)))
  • @rogue-one 是的,所以当你这样做时,你不能在解析 json 之后再引用其他列,对吧?例如,如果我将 json 中的内容展平并想要输出所有列以及新列,那将如何完成?
  • 你看过这个吗:stackoverflow.com/questions/35068792/…——我认为explode方法应该可以帮助你做到这一点。当然 - 当你来自兽人时,它可能不起作用。这可以帮助您提取 JSON stackoverflow.com/questions/34069282/…

标签: apache-spark


【解决方案1】:

我从来没有使用过这样的计算,但我有一个建议给你:

在您自己对列进行任何操作之前,只需检查 sql.functions 包,其中包含一大堆有用的函数来处理列,例如日期提取和格式化、字符串连接和拆分, ...它还提供了一些函数来处理 json 对象,例如:from_jsonjson_tuple

要使用这些方法,您只需导入它们并在 select 方法中调用它们,如下所示:

import spark.implicits._
import org.apache.spark.sql.functions._
val transofrmedDf = df.select($"externalid", $"itemid", … from_json($"internalitem", schema), $"version" …)

首先,您必须为您的 json 列创建一个架构并将其放入 schema 变量中

希望对你有帮助。

【讨论】:

  • 谢谢。因此,如果我写出 transofrmedDf 它将包含根据模式解析的 json。但不是其他列。我是 Spark DataFrame 的新手,可以说:df.select($"externalid", $"itemid", … from_json($"internalitem", schema), $"version" …)
  • @dlamblin 当然,这显然是可能的!
  • 好的,这回答了最初的主要问题。下一部分是将 json 中的内容映射到“想要得到类似的东西”或“扁平化……爆炸”视图。我想我会提出一个单独的问题。 stackoverflow.com/q/44192994/459
猜你喜欢
  • 1970-01-01
  • 2020-01-29
  • 1970-01-01
  • 2021-10-24
  • 2021-03-03
  • 2020-03-01
  • 2016-08-30
  • 2018-12-29
  • 2018-06-05
相关资源
最近更新 更多