Как проанализировать JSON, содержащий строковое свойство, представляющее JSON - PullRequest
0 голосов
/ 05 апреля 2019

У меня есть много JSON со следующей структурой.

{
    "p1":"v1",
    "p2":"v2",
    "p3":"v3",
    "modules": "{ \"nest11\":\"n1v1\", \"nest12\":\"n1v2\", \"nest13\": { \"nest21\": \"n2v1\" }  }"
}

Как с этим разобраться?

v1, v2, v3, n1v1, n1v2, n2v1

Это не проблема для извлечения "v1, v2, v3", но как получить доступ к "n1v1, n1v2, n2v1" С API фрейма Spark Data

Ответы [ 3 ]

1 голос
/ 06 апреля 2019

Один из подходов заключается в использовании неявного класса DataFrameFlattener , найденного на официальном сайте кирпичей данных.

Сначала вам необходимо определить схему JSON для модулей * 1007.* столбец, то вы выравниваете информационный кадр, как показано ниже.Здесь я предполагаю, что файл test_json.txt будет иметь следующее содержимое:

{
    "p1":"v1",
    "p2":"v2",
    "p3":"v3",
    "modules": "{ \"nest11\":\"n1v1\", \"nest12\":\"n1v2\", \"nest13\": { \"nest21\": \"n2v1\" }  }"
}

Вот код:

import org.apache.spark.sql.functions.col
import org.apache.spark.sql.{Column, DataFrame}
import org.apache.spark.sql.types.{DataType, StructType, StringType}

implicit class DataFrameFlattener(df: DataFrame) {
  def flattenSchema: DataFrame = {
    df.select(flatten(Nil, df.schema): _*)
  }

  protected def flatten(path: Seq[String], schema: DataType): Seq[Column] = schema match {
    case s: StructType => s.fields.flatMap(f => flatten(path :+ f.name, f.dataType))
    case other => col(path.map(n => s"`$n`").mkString(".")).as(path.mkString(".")) :: Nil
  }
}

val schema = (new StructType)
  .add("nest11", StringType)
  .add("nest12", StringType)
  .add("nest13", (new StructType).add("nest21", StringType, false))

val df = spark.read
  .option("multiLine", true).option("mode", "PERMISSIVE")
  .json("C:\\temp\\test_json.txt")

df.withColumn("modules", from_json($"modules", schema))
  .select($"*")
  .flattenSchema

И это должен быть вывод:

+--------------+--------------+---------------------+---+---+---+
|modules.nest11|modules.nest12|modules.nest13.nest21|p1 |p2 |p3 |
+--------------+--------------+---------------------+---+---+---+
|n1v1          |n1v2          |n2v1                 |v1 |v2 |v3 |
+--------------+--------------+---------------------+---+---+---+

Пожалуйста, дайте мне знать, если вам нужны дальнейшие разъяснения.

0 голосов
/ 05 апреля 2019

Когда вы получаете элемент «modules», вы на самом деле получаете строку. Вы должны создать эту строку как новый объект JSON. Я не знаю, какой язык вы используете, но вы обычно делаете что-то вроде:

String modules_str = orginalJSON.get("modules");
JSON modulesJSON = new JSON(modules_str);
String nest11_str = modulesJSON.get("nest11");
0 голосов
/ 05 апреля 2019

Все, что вам нужно сделать, это проанализировать строку JSON для фактического объекта JavaScript

const originalJSON = {
  "p1":"v1",
  "p2":"v2",
  "p3":"v3",
  "modules": "{ \"nest11\":\"n1v1\", \"nest12\":\"n1v2\", \"nest13\": { \"nest21\": \"n2v1\" }  }"
}
const { modules, ...rest } = originalJSON
const result = {
  ...rest,
  modules: JSON.parse(modules)
}
console.log(result)
console.log(result.modules.nest11)
...