首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从JSON编码的列中提取值?

如何从JSON编码的列中提取值?
EN

Stack Overflow用户
提问于 2018-07-06 20:58:22
回答 2查看 2.5K关注 0票数 2

我有一个具有以下架构的。

代码语言:javascript
复制
[{ "map": {
    "completed-stages": 1,
    "total-stages": 1 },
    "rec": "test-plan",
    "status": {
        "state": "SUCCESS"
    }
  },
  { "map": {
    "completed-stages": 1,
    "total-stages": 1 },
    "rec": "test-proc",
    "status": {
        "state": "FAILED"
  }
}]

我想将它转换为另一个具有以下模式[{"rec": "test-plan", "status": "SUCCESS"}, {"rec": "test-pROC", "status": "FAILED"}]的DF

我编写了以下代码,但它没有编译,并抱怨编码错误。

代码语言:javascript
复制
val fdf = DF.map(f => {
        val listCommands = f.get(0).asInstanceOf[WrappedArray[Map[String, Any]]]
        val m = listCommands.map(h => {
            var rec = "none"
            var status = "none"

            if(h.exists("status" == "state" -> _)) {
                status = (h.get("status") match {
                    case Some(x) => x.asInstanceOf[HashMap[String, String]].getOrElse("state", "none")
                    case _ => "none"
                })

                if(h.contains("rec")) {
                    rec = (h.get("rec") match {
                        case Some(x: String) => x
                        case _ => "none"
                    })
                }
            }

          Map("status"->status, "rec"->rec)
        })

      val rm = m.flatten
      rm
    })

请建议正确的方法。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-08 17:14:32

这将是一个棘手的问题,因为JSON的顶级元素并不相同,即您有map1map2,因此模式是不一致的。我会与“数据生成器”交谈,并请求进行更改,以便命令的名称由一个单独的元素描述。

给定DataFrame的架构如下:

代码语言:javascript
复制
scala> commands.printSchema
root
 |-- commands: array (nullable = true)
 |    |-- element: string (containsNull = true)

以及其中的元素(行)数:

代码语言:javascript
复制
scala> commands.count
res1: Long = 1

您必须首先分解元素的commands数组,然后访问感兴趣的字段。

代码语言:javascript
复制
// 1. Explode the array
val commandsExploded = commands.select(explode($"commands") as "command")
scala> commandsExploded.count
res2: Long = 2

让我们创建JSON编码记录的模式。可以如下所示。

代码语言:javascript
复制
// Note that it accepts map1 and map2 fields
import org.apache.spark.sql.types._
val schema = StructType(
  StructField("map1",
    StructType(
      StructField("completed-stages", LongType, true) ::
      StructField("total-stages", LongType, true) :: Nil), true) ::
  StructField("map2",
    StructType(
      StructField("completed-stages", LongType, true) ::
      StructField("total-stages", LongType, true) :: Nil), true) ::
  StructField("rec", StringType,true) ::
  StructField("status", StructType(
    StructField("state", StringType, true) :: Nil), true
  ) :: Nil)

在这种情况下,您应该使用json标准函数,它使用带有JSON编码的字符串和模式的列。

代码语言:javascript
复制
val commands = commandsExploded.select(from_json($"command", schema) as "command")
scala> commands.show(truncate = false)
+-------------------------------+
|command                        |
+-------------------------------+
|[[1, 1],, test-plan, [SUCCESS]]|
|[, [1, 1], test-proc, [FAILED]]|
+-------------------------------+

让我们来看看commands数据集的架构。

代码语言:javascript
复制
scala> commands.printSchema
root
 |-- command: struct (nullable = true)
 |    |-- map1: struct (nullable = true)
 |    |    |-- completed-stages: long (nullable = true)
 |    |    |-- total-stages: long (nullable = true)
 |    |-- map2: struct (nullable = true)
 |    |    |-- completed-stages: long (nullable = true)
 |    |    |-- total-stages: long (nullable = true)
 |    |-- rec: string (nullable = true)
 |    |-- status: struct (nullable = true)
 |    |    |-- state: string (nullable = true)

recstatus这样的复杂字段是.-accessible的结构。

代码语言:javascript
复制
val recs = commands.select(
  $"command.rec" as "rec",
  $"command.status.state" as "status")

scala> recs.show
+---------+-------+
|      rec| status|
+---------+-------+
|test-plan|SUCCESS|
|test-proc| FAILED|
+---------+-------+

将其转换为单记录JSON编码的数据集需要Dataset.toJSON,然后是列表标准函数。

代码语言:javascript
复制
val result = recs.toJSON.agg(collect_list("value"))
scala> result.show(truncate = false)
+-------------------------------------------------------------------------------+
|collect_list(value)                                                            |
+-------------------------------------------------------------------------------+
|[{"rec":"test-plan","status":"SUCCESS"}, {"rec":"test-proc","status":"FAILED"}]|
+-------------------------------------------------------------------------------+
票数 1
EN

Stack Overflow用户

发布于 2018-07-08 05:36:45

您没有为df提供模式,所以下面的内容可能不适合您。我将json示例保存在一个test.json文件中,并使用val df=spark.read.option("multiLine",true).json("test.json")读取它,在这种情况下,只需要df.select($"rec",$"status.state").write.json("test1.json")就可以得到您想要的json。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51217523

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档