我正在学习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 filter
的MonadicJValue
用来。 MonadicJValue.filter
的结果是 List[JValue]
。之后执行上述步骤。
关于scala - `JObject(rec) <- someJArray` 在理解中意味着什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27856025/