我遵循了spark流媒体指南,并且能够使用sqlContext.read.json(rdd)
获取我的json数据的sql上下文。问题是其中一个json字段是我想要解析的JSON字符串。
有没有办法在spark sql中完成这个,或者使用ObjectMapper解析字符串并加入其余数据会更容易吗?
为了澄清,JSON的一个值是字符串,其中包含内部引号转义的JSON数据。我正在寻找一种方法来告诉解析器将该值视为字符串化JSON
示例Json
{
"key": "val",
"jsonString": "{ \"too\": \"bad\" }",
"jsonObj": { "ok": "great" }
}
SQLContext如何解析它
root
|-- key: string (nullable = true)
|-- jsonString: string (nullable = true)
|-- jsonObj: struct (nullable = true)
| |-- ok: string (nullable = true)
我希望如何
root
|-- key: string (nullable = true)
|-- jsonString: struct (nullable = true)
| |-- too: string (nullable = true)
|-- jsonObj: struct (nullable = true)
| |-- ok: string (nullable = true)
答案 0 :(得分:4)
您可以使用from_json
功能来解析数据集的列:
import org.apache.spark.sql.functions._
import org.apache.spark.sql.types._
val stringified = spark.createDataset(Seq("{ \"too\": \"bad\" }", "{ \"too\": \"sad\" }"))
stringified.printSchema()
val structified = stringified.withColumn("value", from_json($"value", StructType(Seq(StructField("too", StringType, false)))))
structified.printSchema()
将value
列从string
转换为struct
:
root
|-- value: string (nullable = true)
root
|-- value: struct (nullable = true)
| |-- too: string (nullable = false)
答案 1 :(得分:2)
较旧的RDD API方法(请参阅DataFrame API的已接受答案)
我最终使用Jackson来解析json信封,然后再次解析内部转义字符串。
val parsedRDD = rdd.map(x => {
// Get Jackson mapper
val mapper = new ObjectMapper() with ScalaObjectMapper
mapper.registerModule(DefaultScalaModule)
// parse envelope
val envelopeMap = mapper.readValue[Map[String,Any]](x)
//println("the original envelopeMap", envelopeMap)
// parse inner jsonString value
val event = mapper.readValue[Map[String,Any]](envelopeMap.getOrElse("body", "").asInstanceOf[String])
// get Map that includes parsed jsonString
val parsed = envelopeMap.updated("jsonString", event)
// write entire map as json string
mapper.writeValueAsString(parsed)
})
val df = sqlContext.read.json(parsedRDD)
现在parsedRDD包含有效的json,数据框正确地推断出整个模式。
我认为必须有一种方法可以避免必须序列化到json并再次解析但到目前为止我没有看到任何在RDD上运行的sqlContext API [Map [String,Any]]
答案 2 :(得分:0)
显然
“jsonString”:“{\”too \“:\”bad \“}”
是无效的json数据,修复:并确保整个字符串是有效的json结构。
答案 3 :(得分:0)
你提供的json是错误的,所以修复并给你一个例子。
让我们把json带到下面。 {“key”:“val”,“jsonString”:{“too”:“bad”},“jsonObj”:{“ok”:“great”}}
Spark SQL Json解析器也允许你读取嵌套的json,坦率地说,如果没有提供,它就不完整了,因为你会看到几乎99%的嵌套jsons。
要了解如何访问它,您需要选择使用。 。这是jsonString.too或jsonObj.ok。
以下是理解
的示例scala> val df1 = sqlContext.read.json("/Users/srini/workspace/splunk_spark/file3.json").toDF
df1: org.apache.spark.sql.DataFrame = [jsonObj: struct<ok:string>, jsonString: struct<too:string>, key: string]
scala> df1.show
+-------+----------+---+
|jsonObj|jsonString|key|
+-------+----------+---+
|[great]| [bad]|val|
+-------+----------+---+
scala> df1.select("jsonString.too");
res12: org.apache.spark.sql.DataFrame = [too: string]
scala> df1.select("jsonString.too").show
+---+
|too|
+---+
|bad|
+---+
scala> df1.select("jsonObj.ok").show
+-----+
| ok|
+-----+
|great|
+-----+
希望你能理解。如果您需要更多信息,请回复。它只是父节点。子节点。而已。