使用具有相同名称的嵌套子属性展平Spark JSON数据帧

使用具有相同名称的嵌套子属性展平Spark JSON数据帧,json,scala,apache-spark,dataframe,flatten,Json,Scala,Apache Spark,Dataframe,Flatten,作为Scala/Spark的noob,我有点卡住了,希望能得到任何帮助 我正在将JSON数据导入Spark数据帧。在这个过程中,我最终得到了一个数据帧,该数据帧在JSON输入中具有相同的嵌套结构 我的目标是使用Scala递归地展平整个数据帧(包括数组/字典中最内部的子属性)。 此外,可能存在具有相同名称的子属性。因此,也需要区分它们 此处显示了一个类似的解决方案(不同父级的子属性相同)—— 我希望实现的一个例子如下: { "id": "0001", "type": "donut"

作为Scala/Spark的noob,我有点卡住了,希望能得到任何帮助

我正在将JSON数据导入Spark数据帧。在这个过程中,我最终得到了一个数据帧,该数据帧在JSON输入中具有相同的嵌套结构

我的目标是使用Scala递归地展平整个数据帧(包括数组/字典中最内部的子属性)。

此外,可能存在具有相同名称的子属性。因此,也需要区分它们

此处显示了一个类似的解决方案(不同父级的子属性相同)——

我希望实现的一个例子如下:

{
    "id": "0001",
    "type": "donut",
    "name": "Cake",
    "ppu": 0.55,
    "batters":
        {
            "batter":
                [
                    { "id": "1001", "type": "Regular" },
                    { "id": "1002", "type": "Chocolate" },
                    { "id": "1003", "type": "Blueberry" },
                    { "id": "1004", "type": "Devil's Food" }
                ]
        },
    "topping":
        [
            { "id": "5001", "type": "None" },
            { "id": "5002", "type": "Glazed" },
            { "id": "5005", "type": "Sugar" },
            { "id": "5007", "type": "Powdered Sugar" },
            { "id": "5006", "type": "Chocolate with Sprinkles" },
            { "id": "5003", "type": "Chocolate" },
            { "id": "5004", "type": "Maple" }
        ]
}
相应的平坦输出火花DF结构为:

{
    "id": "0001",
    "type": "donut",
    "name": "Cake",
    "ppu": 0.55,
    "batters_batter_id_0": "1001", 
    "batters_batter_type_0": "Regular",
    "batters_batter_id_1": "1002", 
    "batters_batter_type_1": "Chocolate",
    "batters_batter_id_2": "1003", 
    "batters_batter_type_2": "Blueberry",
    "batters_batter_id_3": "1004", 
    "batters_batter_type_3": "Devil's Food",
    "topping_id_0": "5001",
    "topping_type_0": "None",
    "topping_id_1": "5002", 
    "topping_type_1": "Glazed",
    "topping_id_2": "5005", 
    "topping_type_2": "Sugar",
    "topping_id_3": "5007", 
    "topping_type_3": "Powdered Sugar",
    "topping_id_4": "5006", 
    "topping_type_4": "Chocolate with Sprinkles",
    "topping_id_5": "5003", 
    "topping_type_5": "Chocolate",
    "topping_id_6": "5004", 
    "topping_type_6": "Maple"
}
之前没有与Scala和Spark进行过大量的合作,我不确定如何继续

最后,如果有人能够请帮助编写通用/非模式解决方案的代码,我将非常感激,因为我需要将其应用于许多不同的集合


非常感谢:)

在我们的一个项目中,有一种可能性我们可以接近它

  • 列表项
  • 定义从数据帧映射行的case类

    case class BattersTopics(id: String, type: String, ..., batters_batter_id_0: String, ..., topping_id_0: String)
    
    val rows = dataSet.collect().toList
    rows.map(bt => Map (
     "id" -> bt.id,
     "type" -> bt.type, 
     "batters" -> Map(
        "batter" -> List(Map("id" -> bt.batters_batter_id_0, "type" -> 
           bt.batters_batter_type_0), ....) // same for the others id and types
        "topping" -> List(Map("id"-> bt.topping_id_0, "type" -> bt.topping_type_0), ...) // same for the others id and type
      ) 
    ))
    
  • 列表项
  • 将dataframe中的每一行映射到case类

    df.map(row => BattersTopics(id = row.getAs[String]("id"), ..., 
       batters_batter_id_0 = row.getAs[String]("batters_batter_id_0 "), ...)
    
    收集到一个列表,并从数据帧生成一个映射[String,Any]

    case class BattersTopics(id: String, type: String, ..., batters_batter_id_0: String, ..., topping_id_0: String)
    
    val rows = dataSet.collect().toList
    rows.map(bt => Map (
     "id" -> bt.id,
     "type" -> bt.type, 
     "batters" -> Map(
        "batter" -> List(Map("id" -> bt.batters_batter_id_0, "type" -> 
           bt.batters_batter_type_0), ....) // same for the others id and types
        "topping" -> List(Map("id"-> bt.topping_id_0, "type" -> bt.topping_type_0), ...) // same for the others id and type
      ) 
    ))
    
  • 使用Jackson将Map[String,Any]转换为Json

  • 示例数据:包含所有不同类型的JSON元素(嵌套JSON映射、JSON数组、长字符串等)

    这是json数据中具有
    arraytype
    structtype
    (映射)值的示例数据

    我们可以为每种类型使用写前两个开关条件,并在未点亮的情况下重复此过程。它将变平为所需的
    Dataframe


    这里是Spark Java API解决方案。

    Hi@dumitru,首先,感谢您的帮助:)据我所见,您已经生成了现有模式到输出模式的映射。但是,我的JSON文件可能有一些额外的字典元素,这些元素可能是我目前考虑的(动态生成的)。因此,需要在未知模式上递归展平的代码。然而,需要考虑儿童吸引力。也有相同的名字。