基本上,我必须使用Spark分析HDFS上的一些复杂的JSON。
我使用“for comprehensions”来(预)过滤JSON和“extract”方法 json4s将其包装到案例类
这个工作正常!
def foo(rdd: RDD[String]) = {
case class View(C: String,b: Option[Array[List[String]]], t: Time)
case class Time($numberLong: String)
implicit val formats = DefaultFormats
rdd.map { jsonString =>
val jsonObj = parse(jsonString)
val listsOfView = for {
JObject(value) <- jsonObj
JField(("v"), JObject(views)) <- value
normalized <- views.map(x => (x._2))
} yield normalized
}
到目前为止一切顺利!
当我尝试将(预)过滤的JSON提取到我的 CaseClass我明白了:
线程“main”中的异常org.apache.spark.SparkException:由于阶段失败而中止作业:任务不可序列化:java.io.NotSerializableException:org.json4s.DefaultFormats $
此处带有提取的代码:
def foo(rdd: RDD[String]) = {
case class View(C: String,b: Option[Array[List[String]]], t: Time)
case class Time($numberLong: String)
implicit val formats = DefaultFormats
rdd.map { jsonString =>
val jsonObj = parse(jsonString)
val listsOfView = for {
JObject(value) <- jsonObj
JField(("v"), JObject(views)) <- value
normalized <- views.map(x => (x._2))
} yield normalized.extract[View]
}
我已经在scala上尝试了我的代码,以及它的工作!我真的很擅长使用hdfs和spark,所以我会很感激。
答案 0 :(得分:6)
Spark序列化RDD转换上的闭包,并且&#39;发货&#39;那些分散执行的工人。 这要求闭包内的所有代码(通常也包含在包含对象中)应该是可序列化的。
查看org.json4s.DefaultFormat$(该特征的伴随对象)的impl:
object DefaultFormats extends DefaultFormats {
val losslessDate = new ThreadLocal(new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"))
val UTC = TimeZone.getTimeZone("UTC")
}
很明显,这个对象不是可序列化的,不能这样做。 (ThreadLocal本身就是不可序列化的)
您似乎没有在代码中使用Date
类型,因此您可以摆脱
implicit val formats = DefaultFormats
或用可序列化的东西替换DefaultFormats?
答案 1 :(得分:3)
这实际上已经修复了; JSON4S可以从版本3.3.0开始序列化:https://github.com/json4s/json4s/issues/137
答案 2 :(得分:0)
解决我问题的方法是,我在implicit val formats = DefaultFormats
循环中使用了rdd.foreach{}
。它解决了我的可序列化异常。
这是我的代码段,解决了该问题:
case class rfId(rfId: String) {}
// ... some code here ...
rdd.foreach { record =>
val value = record.value()
// Bring in default date formats etc and makes json4s serializable
implicit val formats = DefaultFormats
val json = parse(value)
println(json.camelizeKeys.extract[rfId]) // Prints `rfId(ABC12345678)`
}