【问题标题】:Strange behaviour of Scala for-comprehension and json4sScala for-comprehension 和 json4s 的奇怪行为
【发布时间】:2014-10-27 11:04:17
【问题描述】:

下面的代码应该:

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

它在小型测试中表现如预期, 但在 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多?

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • 这是我的第一个想法,但是在上面的代码中使用val txt = Seq("""{"a": 1, "B": 2, " ": 3}{"c": 4}""")只解析第一条记录,parse的返回类型是JValue
    • 等等,parse 返回一个JValue?然后你flatMaping 呢?你确定这不是遍历 json 值的每个字段或类似的吗?
    • JValue 实现了mapflatMap。它的行为有点像OptionJNone 的行为类似于NoneJValue 的其他子类就像被包裹在一个不可见的Some 中一样。
    • 感谢您让我仔细检查。这就是我发现实际问题的方式。
    【解决方案2】:

    我不知道

    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))))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2011-05-09
      • 1970-01-01
      • 1970-01-01
      • 2014-07-04
      • 2019-10-03
      • 1970-01-01
      相关资源
      最近更新 更多