【问题标题】:Can't print all values of a multiple rows json string无法打印多行json字符串的所有值
【发布时间】:2019-08-31 15:41:25
【问题描述】:

我想对多个“行”json 字符串进行一些查询。我所说的多个 json 字符串是指这样组织的 json 字符串:

[{ 
    "id" : 5,
    "name" : "Jemmy overy",
    "data" : {...},
    "link" : "http:...",
},
{ 
    "id" : 6,
    "name" : "John Smith",
    "data" : {...},
    "link" : "http:...",
}] 

这是我尝试做的:

首先,我有 多个 json 文件,我从 HDFS 获得:

val df = spark
.read
.format(com.databricks.spark.avro)
.load(namenodeURI)

此时我的 json 文件的架构分为两个字段:

  • 标题
  • 身体

我要处理的列是 body,所以我使用 spark-sql 只选择了 JSON 格式的数据列。

df.createOrReplaceTempView("Rawdata")
import spark.implicits._
val strBody = spark
 .sql("SELECT body from Rawdata")
 .as[String]
 .collect
 .mkString

记住我有多个 json 文件,所以我有多个主体。我真的不知道如何从查询中获取结果,我试图将其作为字符串获取。

我的目标是对 strBody 字符串进行一些查询。我首先使用编码器将其转换为数据集:

val ds = spark.createDataset(strBody :: Nil)
val schema = Encoders.product[Root].schema
val ds2 = 
 spark
   .read
   .schema(schema)
   .json(ds).as[Root]

Root是一个case类,对应body中的Json schema。

当我想打印我的正文的特定字段的每个内容时,它只打印从我的 sql 查询返回的第一个正文的字段的内容:

ds2.map(x => x.someField.someAnotherNestedField).foreach(println(_))
// print only one element, the first element from the strBody variable

当我从查询中获取字符串以匹配多行json字符串的语法时,我尝试添加前缀后缀和分隔符:

val strBody = spark
 .sql("SELECT body from Rawdata")
 .as[String]
 .collect
 .mkString("[",",\n","]")

由于我使用插入“\n”字符,所以在最后读取数据集时指定了多行选项:

val ds = spark.createDataset(strBody :: Nil)
val schema = Encoders.product[Root].schema
val ds2 = 
 spark
  .read
  .option("multiline","true")
  .schema(schema)
  .json(ds).as[Root]

然后我得到一个 NullPointerException。实际上 ds2 不包含任何值。

有人知道如何解决这个问题吗?

【问题讨论】:

  • 您能否在数据帧上发布与您的代码示例匹配的示例以及printSchema。还有火花版本。

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


【解决方案1】:

我成功解决了这个问题,我就是这样处理的:

我没有创建一个包含查询结果的字符串,而是返回了数据框:

val bodyDF : DataFrame = spark
 .sql("SELECT body from Rawdata")

之后,我从数据框中创建了一个字符串数据集:

val bodyDS : DataSet[String] = bodyDF.as[String]

最后我创建了一个根数据集:

val finalDS : DataSet[Root] = spark
                               .read
                               .json(bodyDS)
                               .as[Root]

这种说法现在很管用:

finalDS.map(x => x.someField.someAnotherNestedField).foreach(println(_))

我希望它会帮助别人!

【讨论】:

    猜你喜欢
    • 2020-10-29
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多