如何在scala中获取JSON的结构

如何在scala中获取JSON的结构,json,scala,apache-spark,Json,Scala,Apache Spark,我有很多没有结构化的JSON文件,我想得到一个更深层次的元素和所有元素 例如: { "menu": { "id": "file", "popup": { "menuitem": { "module"{ "-vdsr": "New", "-sdst": "Open", "-mpoi": "Close"

我有很多没有结构化的JSON文件,我想得到一个更深层次的元素和所有元素

例如:

{
"menu": {
    "id": "file",
    "popup": {
        "menuitem": {
                  "module"{
                      "-vdsr": "New",
                      "-sdst": "Open",
                      "-mpoi": "Close" }
        ...
    }
}
在这种情况下,结果将是:

menu.popup.menuitem.module.-vdsr
menu.popup.menuitem.module.-sdst
menu.popup.menuitem.module.-mpoi
我尝试了
Jackson
Json4s
,它们可以有效地执行最后一个值,但我不知道如何获得整个结构


我想让它在非常大的JSON文件上运行ApacheSpark作业,每个文件的结构都非常复杂。我也尝试过sparkSQL,但如果我不知道整个结构,我就无法得到它。

您要求做的基本上是一个对象的定义,其中JSON对象被认为是具有命名分支的节点,其他JSON类型被认为是叶子。有很多方法可以做到这一点。您可以考虑创建一个递归函数来探索整个树。下面是一个在
PlayJson
中工作的示例,但在其他库中应该没有什么不同:

import play.api.libs.json._
def unfold(json: JsValue): Seq[String] = json match {
    case JsObject(kvps) => kvps.flatMap {
        case (key, value) => unfold(value).map(path => s"$key.$path")
    }
    case _ => Seq("")
}
新方法的优点在于,当您加载数据时,它会自动推断模式。
它通过对整个数据集进行一次性传递来实现

我建议您加载json,然后进行转换,看看能得到什么。您可以删除或选择列的子集、筛选行、聚合、映射到列上,等等

例如:

// you can use globing to load multiple files
val jsonTbl = sqlContext.load("path to json file", "json")

// print the inferred schema
jsonTbl.printSchema

// now you can use the DataFrame API to transform the data set, e.g.
val outputTbl = jsonTbl
    .filter("menu.popup.menuitem.module.-vdsr = 'Some value'")
    .groupBy("menu.popup.menuitem.module.-vdsr").count
    .select("menu.popup.menuitem.module.-sdst", "other fields/columns")

outputTbl.show