Scala for-comprehension和json4s的奇怪行为

时间:2014-10-27 11:04:17

标签: scala apache-spark scala-2.10 for-comprehension json4s

以下代码应:

  • 遍历一系列字符串
  • 将每个解析为json,
  • 过滤掉在大多数语言中名称不能用作标识符的字段
  • 小写rmaining名称
  • 将结果序列化为字符串

在小型测试中表现如预期, 但是在8.6M项目的实时数据序列上,输出序列明显更长 而不是输入序列:

import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.apache.spark._

val txt = sc.textFile("s3n://...")
val patt="""^[a-zA-Z]\w*$""".r.findFirstIn _
val json = (for {
         line <- txt
         JObject(children) <- parse(line)
         children2 = (for {
           JField(name, value) <- children

           // filter fields with invalid names
           // patt(name) returns Option[String]
           _ <- patt(name)

         } yield JField(name.toLowerCase, value))
} yield compact(render(JObject(children2))))

我已经检查过它实际上增加了唯一商品的数量, 所以这不仅仅是重复项目。 鉴于我对Scala理解的理解和json4s,我看不出这是怎么回事。 大型实时数据收集是Spark RDD,而我的测试是使用普通的Scala Seq,但这不应该有任何区别。

上述代码中json如何拥有比txt更多的元素?

2 个答案:

答案 0 :(得分:1)

也许parse(line)正在为一行返回多个JSON对象?

答案 1 :(得分:0)

我不知道

JObject(children) <- parse(line)

parse的结果内递归匹配。因此,即使parse返回单个值,但当存在嵌套对象时,它们将作为children的单独绑定返回。 答案是使用

JObject(children) = parse(line)

正确的代码是:

import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.apache.spark._

val txt = sc.textFile("s3n://...")
val patt="""^[a-zA-Z]\w*$""".r.findFirstIn _
val json = (for {
         line <- txt
         JObject(children) = parse(line) // CHANGED <- TO =
         children2 = (for {
           JField(name, value) <- children

           // filter fields with invalid names
           // patt(name) returns Option[String]
           _ <- patt(name)

         } yield JField(name.toLowerCase, value))
} yield compact(render(JObject(children2))))