How to get all columns names in spark in a nested structure that are of type string

Viewed 825

So I have this schema, and I want to get all column names that have strings on it

  val schema = StructType(Array(
    StructField("id", IntegerType),
    StructField("nested", StructType(Array(
      StructField("value1", StringType),
      StructField("value2", StringType)
    ))),
    StructField("name", StringType)
    ))

I want to get

  Seq("nested.value1","nested.value2","name")

This is just an example, but it should work and multiple nested levels

2 Answers
def extractNames(schema: StructType): Seq[String] = {
  schema.fields.flatMap {
    field =>
      field.dataType match {
        case structType: StructType =>
          extractNames(structType).map(field.name + "." + _)
        case _: StringType =>
          field.name :: Nil
        case _ =>
          Nil
      }
  }
}

Test case:

val schema = StructType(Array(
  StructField("id", IntegerType),
  StructField("nested", StructType(Array(
    StructField("value1", StringType),
    StructField("value2", StringType),
    StructField("struct", StructType(Array(
      StructField("value1", IntegerType),
      StructField("value2", StringType)
    )))
  ))),
  StructField("name", StringType)
))

val names = extractNames(schema)
println(names.mkString(", "))

Output:

nested.value1, nested.value2, nested.struct.value2, name

For example, this could be done as following code:

def getName(f: StructField, prefix: String = ""): Seq[String] = {
  val newPrefixOrName = if (prefix.isEmpty) f.name else s"$prefix.${f.name}"
  f.dataType match {
    case StructType(fields) =>
      fields.flatMap(x => getName(x, newPrefixOrName))
    case StringType =>
      Seq(newPrefixOrName)
    case _ => Nil
  }
}

def getNames(s: StructType): Seq[String] = s.fields.flatMap { f => getName(f) }

This code goes over the the array of the fields and if the specific value is of StructType, then it iterates over its fields. This code should work for deeply nested structs as well.

Related