将Case类中的Map类型转换为StructField类型

时间:2016-01-06 09:22:45

标签: scala apache-spark

我有一个案例类,我想在Spark中转换为架构

case class test(request1:Map[String, Any],response1:Option[String] = None,)

如何将此类转换为架构对象

val mySchema = StructType(
StructField("request1", Map[String, Any], false),StructField(" response1", Option[String],true))

MapType和选项在DataType

中不可用

2 个答案:

答案 0 :(得分:7)

无法使用此案例类创建DataFrame架构。虽然Spark支持地图MapTypeOptions使用包裹类型处理Nones已转换为NULLs,但不支持Any类型的架构。

假设您将Value类型更改为String

case class Test(request1: Map[String, String], response1: Option[String] = None)

相应的模式应如下所示:

StructType(Seq(
   StructField("request1", MapType(StringType, StringType, true), true),
   StructField("response1", StringType, true)
))

答案 1 :(得分:1)

正如@ zero323已经雄辩地说,即使你可以使用MapType,在你的情况下它可能不是最好的。您的请求和响应可能已经过结构化,您应该投入一些时间来定义该结构/模式。例如,您可以以编程方式一次定义所有字符串类型列,所有int类型列都以编程方式定义,如下面的代码所示。

在sql中,Option转换为可以为空的StructField的第三个参数,它是真或假 - 大多数时候你将它设置为true,因此允许空值。

您可以像这样定义嵌套结构:

import org.apache.spark.sql.types._

case class Request(url:String, enc:String)
case class Response(code:Int, body:String)
case class Record( request:Request, response:Response)

val names = Array("url", "enc")
val requestStructType = StructType( names.map( name => StructField(name, StringType, true)))

/// example of StructType with differing types, programmaticaly, add more field names if needed
val respNamesInt = Array("code")
val respNamesString = Array("body")
val responseStructType =
      StructType( respNamesInt.map( name => StructField(name, IntegerType, true)) ++
                  respNamesString.map( name => StructField(name, StringType, true)))

// example of nested structures
val recordStructType =
      StructType( Array(StructField("request", requestStructType, false), // nullable = false
                        StructField("response", responseStructType, true))) // nullable = true