Spark Scala:将StructType转换为String

时间:2018-10-26 10:11:19

标签: scala apache-spark apache-spark-sql

我将json读为:

select distinct r.account_encypted_value from person_department_ref r order by r.account

我阅读了来自不同主题的消息,因此无法指定显式架构。 某些消息包含带有嵌套json的字段,它们将转换为StructType。例如:

val df = spark.read.json(rdd)

如何将其转换为String?我需要将“儿子”字段读取为字符串:

{"name": "John", "son": {"name":"Tom"}}

使用"{\"name\":\"Tom\"}" 方法或sql函数失败:

cast

错误:

df.selectExpr("cast(son as string)")

2 个答案:

答案 0 :(得分:3)

您可以使用to_json轻松返回一个字符串

df.select(to_json(df("son")))

答案 1 :(得分:0)

对不起,我误解了你的问题。我以为您有不同的架构,有时字段作为结构返回,有时作为字符串返回,并且您想每次将其转换为字符串。我将答案留作参考。


我在本地尝试了一个小测试用例,很显然,如果我让Spark干扰模式,它会将我的“ son”字段视为String。我不知道您如何构建处理逻辑,但是作为“替代方法”,您可以尝试手动指定模式并输入“ son”作为String?

val testDataset =
  """
    | {"name": "John", "son": {"name":"Tom"}}
    | {"name": "John", "son": "Tom"}
  """.stripMargin
val testJsonFile = new File("./test_json.json")
FileUtils.writeStringToFile(testJsonFile, testDataset)


val schema = StructType(
  Seq(StructField("name", DataTypes.StringType, true), StructField("son", DataTypes.StringType, true))
)
val sparkSession = SparkSession.builder()
    .appName("Test inconsistent field type").master("local[*]").getOrCreate()
val structuredJsonData = sparkSession.read.schema(schema).json(testJsonFile.getAbsolutePath)
import sparkSession.implicits._

val collectedDataset = structuredJsonData.map(row => row.getAs[String]("son")).collect()
println(s"got=${collectedDataset.mkString("---")}")
structuredJsonData.printSchema()

它打印:

got={"name":"Tom"}---Tom
root
 |-- name: string (nullable = true)
 |-- son: string (nullable = true)

您仍然可以尝试定义自定义映射功能。但是我不确定它是否会起作用,因为当我尝试将具有StructType的架构应用于具有StringType的JSON时,整行将被忽略(两个字段均为空值):

val testDataset =
  """
    | {"name": "John", "son": {"name":"Tom"}}
    | {"name": "John", "son": "Tom2"}
  """.stripMargin
val testJsonFile = new File("./test_json.json")
FileUtils.writeStringToFile(testJsonFile, testDataset)

val schema = StructType(
  Seq(StructField("name", DataTypes.StringType, true), StructField("son", StructType(Seq(StructField("name", DataTypes.StringType, true))))
  )
)
val sparkSession = SparkSession.builder()
    .appName("Test inconsistent field type").master("local[*]").getOrCreate()
val structuredJsonData = sparkSession.read.schema(schema).json(testJsonFile.getAbsolutePath)
println(s"got=${structuredJsonData.collect().mkString("---")}")
structuredJsonData.printSchema()

它打印:

got=[John,[Tom]]---[null,null]
root
 |-- name: string (nullable = true)
 |-- son: struct (nullable = true)
 |    |-- name: string (nullable = true)