Scala 如何将Spark数据帧转换为JSONObject
我的目标是将数据帧转换为JSONObject的有效JSONArray 我目前正在使用:Scala 如何将Spark数据帧转换为JSONObject,scala,apache-spark,Scala,Apache Spark,我的目标是将数据帧转换为JSONObject的有效JSONArray 我目前正在使用: val res = df.toJSON.collect() 但是我得到了一个数组[String]——JSON转义字符串数组,即: ["{\"url\":\"http://www.w3schools.com/html/html_form_action.asp?user=123\",\"subnet\":\"32.2.208.1\",\"country\":\"\",\"status_code\":\"200\
val res = df.toJSON.collect()
但是我得到了一个数组[String]——JSON转义字符串数组,即:
["{\"url\":\"http://www.w3schools.com/html/html_form_action.asp?user=123\",\"subnet\":\"32.2.208.1\",\"country\":\"\",\"status_code\":\"200\"}"]
我正在寻找一种将这些字符串转换为实际JSONObject的方法,我找到了一些建议的解决方案,但我正在寻找更干净的方法
我尝试使用org.json库将每个字符串转换为JSONObject,但显然它不是一个可序列化的对象
有什么建议吗?有没有可以使用的fast Scala JSON库
或者通常建议如何使用toJSON方法
更新
这有点浪费,但这个选项对我很有用:
val res = df.toJSON.map(new JSONObject(_).toString).collect()
因为JSONObject是不可序列化的,所以我可以使用它的toString来获取有效的JSON格式
如果您对我如何改进它还有任何建议,请告诉我。您可以使用它将字符串解析为case类:
import spray.json._
import DefaultJsonProtocol._
case class Data(url: String, subnet: String, country: String, status_code: String)
implicit val dataFormat = jsonFormat4(Data)
val source = Array("{\"url\":\"http://www.w3schools.com/html/html_form_action.asp?user=123\",\"subnet\":\"32.2.208.1\",\"country\":\"\",\"status_code\":\"200\"}")
val data = source(0).parseJson.convertTo[Data]
您可以使用DataframeWriter类
df.write.json(path)
如果输出文件具有多个记录/分区,则可能会创建多个部件文件。然后,您可以编写一个简单的合并实用程序来合并hdfs/本地文件系统中的零件文件
在这种情况下,输出是一个小文件-您可以使用coalesce()
然后,您可以将其读回DF。您可以:
Array[Row]
map[String,Any]
-结果将通过Array[map[String,Any]]
我还考虑了使用用例类的选项,但是有80多个嵌套字段。所以创建一个会非常复杂。我希望以某种方式使用dataframe模式,如果您只想从JSON中获取一些数据,只需要为所需的位定义case类层次结构。例如,上面的内容也适用于
案例类数据(url:String,subnet:String)
。是的,我知道,但我几乎需要整个结构。我确实在一些内部UDF中使用案例类来操作一些数据。但结果应该包括几乎所有内容。这也是为什么我更喜欢使用spark toJSON函数,而不是提供我自己的编写器。您可以使用数据帧的示例数据进行更新吗?当我使用toJSON
时,这些引号不会转义。我用的是Spark 1.6。@philantrovert,这很奇怪,我们用的是Spark 1.6.1。我在网上看到的关于这个问题的所有问题都表明格式是相同的。@RameshMaharjan,对不起,我不能提供数据帧结构,这不是我的私人代码。但是,如果有帮助的话,我可以说它有两个嵌套字段。我知道我可以从数据帧中提取模式,我是否可以使用该模式来编写JSONObject?@LiranBo org.codehaus.jettison.json.JSONObject确实是一个可序列化的对象。感谢您的建议,但性能是一个严重的问题。我无法将数据写入文件,然后再次读取它们。
df.coalesce(1).write.json(path)
implicit val formats = DefaultFormats
val dataFrame = (1 to 10)
.map(i => ("value" + i, i))
.toDF("name", "value")
val maps = dataFrame
.collect
.map(
row => dataFrame
.columns
.foldLeft(Map.empty[String, Any])
(
(acc, item) => acc + (item -> row.getAs[Any](item))
)
)
val json = Serialization.write(maps)
println(json)
I will show how dataframe converted into Json object list in spark.
I/P: Dataframe
O/P Json : [{ "id":"111","Loc":"Pune"},{"id":"2222","Loc":"Mumbai"}]
Sol:->
1] Create Person POJO having id and loc fields.
2] Suppose dataframe named 'myDF'
3] myDF.collect.foreach { record =>
val recMap = record.getValuesMap(myDF.columns).toMap[Any, Any]
val person =new Person
person.setLoc(recMap("LOC"))
jsonList.append(person) //List of Person obj
}
val gson = new Gson //GSON lib
jsonStr = gson.toJson(jsonList.asJava)