Scala 如何将Spark数据帧转换为JSONObject

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\

我的目标是将数据帧转换为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\"}"]
我正在寻找一种将这些字符串转换为实际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]]
  • 序列化为JSON

  • 我还考虑了使用用例类的选项,但是有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)