scala - `JObject(rec) <- someJArray` 在理解中意味着什么

标签 scala lift json4s

我正在学习Json4s图书馆。

我有一个像这样的 json 片段:

{
    "records":[
        {
            "name":"John Derp",
            "address":"Jem Street 21"
        },
        {
            "name":"Scala Jo",
            "address":"in my sweet dream"
        }
    ]
}

而且,我有 Scala 代码,它将 json 字符串转换为 map 列表,如下所示:

import org.json4s._
import org.json4s.JsonAST._
import org.json4s.native.JsonParser

  val json = JsonParser.parse( """{"records":[{"name":"John Derp","address":"Jem Street 21"},{"name":"Scala Jo","address":"in my sweet dream"}]}""")

  val records: List[Map[String, Any]] = for {
    JObject(rec) <- json \ "records"
    JField("name", JString(name)) <- rec
    JField("address", JString(address)) <- rec
  } yield Map("name" -> name, "address" -> address)

  println(records)

records的输出屏幕显示如下:

List(Map(name -> John Derp, address -> Jem Street 21), Map(name -> Scala Jo, address -> in my sweet dream))

我想了解 for 里面的行是什么循环的意思。例如,这行的含义是什么:

JObject(rec) <- json \ "records"

据我了解,json \ "records"产生 JArray对象,但为什么它被获取为 JObject(rec)<- 的左侧? JObject(rec)是什么意思?句法? rec在哪里?变量从何而来?是JObject(rec)意味着实例化一个新的 JObject类(class)来自 rec输入?

顺便说一句,我有 Java 编程背景,因此如果您能向我展示上述循环的 Java 等效代码也会很有帮助。

最佳答案

您有以下类型层次结构:

  sealed abstract class JValue {
    def \(nameToFind: String): JValue = ???
    def filter(p: (JValue) => Boolean): List[JValue] = ???
  }

  case class JObject(val obj: List[JField]) extends JValue
  case class JField(val name: String, val value: JValue) extends JValue
  case class JString(val s: String) extends JValue
  case class JArray(val arr: List[JValue]) extends JValue {
    override def filter(p: (JValue) => Boolean): List[JValue] = 
      arr.filter(p)
  }

您的 JSON 解析器返回以下对象:

  object JsonParser {
    def parse(s: String): JValue = {
      new JValue {
        override def \(nameToFind: String): JValue =
          JArray(List(
            JObject(List(
              JField("name", JString("John Derp")),
              JField("address", JString("Jem Street 21")))),
            JObject(List(
              JField("name", JString("Scala Jo")),
              JField("address", JString("in my sweet dream"))))))
      }
    }
  }

  val json = JsonParser.parse("Your JSON")

Scala 编译器在底层生成以下内容:

  val res = (json \ "records")
    .filter(_.isInstanceOf[JObject])
    .flatMap { x =>
      x match {
        case JObject(obj) => //
          obj //
            .withFilter(f => f match {
              case JField("name", _) => true
              case _                 => false
            }) //
            .flatMap(n => obj.withFilter(f => f match {
              case JField("address", _) => true
              case _                    => false
            }).map(a => Map(
              "name" -> (n.value match { case JString(name) => name }),
              "address" -> (a.value match { case JString(address) => address }))))
      }
    }

第一行JObject(rec) <- json \ "records"是可能的,因为 JArray.filter返回List[JValue] (即 List[JObject] )。这里 List[JValue] 的每个值映射到JObject(rec)与模式匹配。

Rest 调用是一系列带有模式匹配的 flatMap 和 map(这就是 Scala 理解的工作方式)。

我使用了 Scala 2.11.4。

当然,match上面的表达式是使用一系列类型检查和强制转换来实现的。

更新:

当您使用Json4s时库中有一个来自 JValue 的隐式转换至org.json4s.MonadicJValue 。请参阅package object json4s :

implicit def jvalue2monadic(jv: JValue) = new MonadicJValue(jv)

此处使用此转换:JObject(rec) <- json \ "records" 。第一,json转换为MonadicJValue ,然后def \("records")应用,则 def filter用于 def \ 的结果这是 JValue ,然后再次隐式转换为 MonadicJValue ,然后def filterMonadicJValue用来。 MonadicJValue.filter的结果是 List[JValue] 。之后执行上述步骤。

关于scala - `JObject(rec) <- someJArray` 在理解中意味着什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27856025/

相关文章:

scala - 如何使用 Squeryl 在 Lift 中实际处理 List[FieldError]

java - 如何在json中指定特定的对象路径

scala - SBT 0.13.1 离线

json - Lift Framework无法反序列化JSON数据

scala - ActorRefs 作为 Akka 中消息的一部分(java.io.NotSerializableException)

scala - 提升 - 未找到代码片段失败方法

json4s - json4s中是否有针对UUID的开箱即用的(反)序列化器?

scala - 使用 json4s 序列化带有特征混合的案例类

scala - 如何在 play framework2.5 的对象中正确注入(inject) play.api.Configuration?

java - 在 Java 中使用 Scala 类型(类型不匹配)