我需要从scala中的嵌套json文件创建一个火花数据帧

时间:2019-01-22 20:38:05

标签: json scala apache-spark

我有一个看起来像这样的Json文件

{
  "tags": [
    {
      "1": "NpProgressBarTag",
      "2": "userPath",
      "3": "screen",
      "4": 6,
      "12": 9,
      "13": "buttonName",
      "16": 0,
      "17": 10,
      "18": 5,
      "19": 6,
      "20": 1,
      "35": 1,
      "36": 1,
      "37": 4,
      "38": 0,
      "39": "npChannelGuid",
      "40": "npShowGuid",
      "41": "npCategoryGuid",
      "42": "npEpisodeGuid",
      "43": "npAodEpisodeGuid",
      "44": "npVodEpisodeGuid",
      "45": "npLiveEventGuid",
      "46": "npTeamGuid",
      "47": "npLeagueGuid",
      "48": "npStatus",
      "50": 0,
      "52": "gupId",
      "54": "deviceID",
      "55": 1,
      "56": 0,
      "57": "uiVersion",
      "58": 1,
      "59": "deviceOS",
      "60": 1,
      "61": 0,
      "62": "channelLineupID",
      "63": 2,
      "64": "userProfile",
      "65": "sessionId",
      "66": "hitId",
      "67": "actionTime",
      "68": "seekTo",
      "69": "seekFrom",
      "70": "currentPosition"
    }
  ]
}

我尝试使用创建数据框

val path = "some/path/to/jsonFile.json"
val df = sqlContext.read.json(path)
df.show()

运行此命令我会得到

df: org.apache.spark.sql.DataFrame = [_corrupt_record: string]

我们如何基于“标签”键的内容创建df?我所需要做的就是从“标签”中提取数据并应用案例类

case class ProgLang (id: String, type: String )

我需要将此json数据转换为具有两个列名.toDF(id,Type)的数据帧 任何人都可以阐明这个错误吗?

3 个答案:

答案 0 :(得分:0)

您可以使用Circe修改JSON。

鉴于您的值有时是 Strings ,有时是 Numbers ,所以这很复杂。

import io.circe._, io.circe.parser._, io.circe.generic.semiauto._

val json = """ ... """ // your JSON here.
val doc = parse(json).right.get
val mappedDoc = doc.hcursor.downField("tags").withFocus { array =>
  array.mapArray { jsons =>
    jsons.map { json =>
      json.mapObject { o =>
        o.mapValues { v =>
          // Cast numbers to strings.
          if (v.isString) v else Json.fromString(v.asNumber.get.toString)
        }
      }
    }
  }
}

final case class ProgLang(id: String, `type`: String )
final case class Tags(tags: List[Map[String, String]])
implicit val TagsDecoder: Decoder[Tags] = deriveDecoder

val tags = mappedDoc.top.get.as[Tags]
val data = for {
  tag <- res29.tags
  (id, _type) <- tag
} yield ProgLang(id, _type)

现在您有了ProgLang的列表,可以直接从中创建一个DataFrame,将其保存为文件,每行每个 JSON ,将其保存为< strong> CSV 文件等...
如果文件很大,可以在转换时使用fs2进行流式传输,通过 Circe 可以很好地integrates


免责声明::我远不是Circe的“专业人士”,这似乎让做“简单任务”的事情变得过于复杂,也许还有更好的选择/更清洁的方式(也许使用光学元件?),但是嘿!有用! -无论如何,如果有人知道解决此问题的更好方法,请随时编辑问题或提供您的问题

答案 1 :(得分:0)

val path = "some/path/to/jsonFile.json"
spark.read
  .option("multiLine", true).option("mode", "PERMISSIVE")
  .json(path)

答案 2 :(得分:0)

如果您的json文件不是很大,请尝试以下代码

    val spark = SparkSession.builder().getOrCreate()
    val df = spark.read.json(spark.sparkContext.wholeTextFiles("some/path/to/jsonFile.json").values)