Spark Scala: приведение типа структуры к строке - PullRequest
0 голосов
/ 26 октября 2018

Я читаю JSON как:

val df = spark.read.json(rdd)

Я читаю сообщения из разных тем, поэтому не могу указать явную схему. Некоторые сообщения содержат поля с вложенным json, и они преобразуются в StructType. Например:

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

Как привести его к String? Мне нужно прочитать поле "сын" как String:

"{\"name\":\"Tom\"}"

Использование метода cast или функции sql завершается ошибкой:

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

Ошибка:

java.lang.String is not a valid external type for schema of struct<name:string>

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Вы можете легко сделать это с помощью to_json, который возвращает строку

df.select(to_json(df("son")))
0 голосов
/ 26 октября 2018

Извините, я неправильно понял ваш вопрос.Я думал, что у вас была другая схема, и иногда поле возвращалось как структура, а иногда как строка, и вы хотели каждый раз преобразовывать ее в строку.Я оставляю ответ только для информационных целей.


Я пробовал небольшой тестовый пример локально, и, по-видимому, если я позволю Spark вмешиваться в схему, он считает мое поле "сын" строкой.Я не знаю, как вы строите логику обработки, но в качестве «обходного пути» вы можете попытаться указать схему вручную и ввести «son» в качестве строки?

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 к JSON с StringType, вся строка игнорируется (нулевые значения в обоих полях):

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()

Itотпечатки:

got=[John,[Tom]]---[null,null]
root
 |-- name: string (nullable = true)
 |-- son: struct (nullable = true)
 |    |-- name: string (nullable = true)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...