Scala 使用JSON字符串中的嵌套映射

Scala 使用JSON字符串中的嵌套映射,scala,Scala,给定如下JSON字符串: {"Locations": {"list": [ {"description": "some description", "name": "the name", "id": "dev123"}, {"description": "other description", "name": "other name", "id": "dev59"} ] } } 我想从解析上述字符串的函数返回一个“id”列表JSON.parseF

给定如下JSON字符串:

{"Locations":
  {"list":
    [
      {"description": "some description", "name": "the name", "id": "dev123"},
      {"description": "other description", "name": "other name", "id": "dev59"}
    ]
  }
}
我想从解析上述字符串的函数返回一个“id”列表
JSON.parseFull()
(来自
scala.util.parsing.JSON
)为我提供类型为
Option[Any]
的结果。Scala REPL将其显示为
Some(地图位置->地图(列表->列表)(地图(id->dev123,…
),作为Scala的初学者,我不知道该怎么做

建议“将其视为一个集合或monad并使用map、flatMap、filter或foreach”。顶层元素是一个选项[Any],但是应该是一个包含单键“Locations”的映射,该映射应该包含一个单键“list”最后是一个列表。在Scala中,编写函数检索“id”的惯用方法是什么?

这就是您需要的吗?(使用lift json)


由于返回的结果是Any is everywhere,因此您必须强制转换。请使用以下方法之一:

class CC[T]{def unapply(a:Any):Option[T]=Some(a.asInstanceOf[T])]
对象M扩展CC[Map[String,Any]]
对象L扩展CC[列表[任何]]
对象S扩展CC[String]
对象D扩展CC[Double]
对象B扩展CC[布尔值]
为了{

一些(M(map))首先,您应该将json从任意类型转换为正确类型:

val json = anyJson.asInstanceOf[Option[Map[String,List[Map[String,String]]]]]
然后,您可以使用
map
方法从选项中提取ID:

val ids = json.map(_("Locations")("list").map(_("id"))).getOrElse(List())

对于这类任务,您应该看一看。我也是scala初学者,但从我搜索的内容来看,这似乎是最友好的语法。下面是一个简短的示例,取自:


在JSON之子的一个分支中,这将起作用。请注意,我没有使用解析器。并不是说它不存在。只是使用生成器方法创建JSON对象更容易:

scala> import nl.typeset.sonofjson._
import nl.typeset.sonofjson._

scala> var all = obj(
     |   locations = arr(
     |     obj(description = "foo", id = "807",
     |     obj(description = "bar", id = "23324"
     |   )
     | )

scala> all.locations.map(_.id).as[List[String]]
res2: List[String] = List(23324, 807)
或使用一个字母来理解:

scala> (for (location <- all.locations) yield location.id).as[List[String]]
res4: List[String] = List(23324, 807)

scala>(对于(位置),我认为类型不完整-当我使用
anyJson.asInstanceOf[Option[Map[String,Map[String,List[Map[String,String]].][
。它是如何工作的呢?
asInstanceOf
是我读到的一个运行时强制转换。我假设当给定的任何对象不同时,它会抛出一个异常。顺便问一下,
映射了什么(“位置”)(“列表”)…
mean?是的,
asInstanceOf
将抛出异常。但是,由于JVM中的类型擦除,
map(u(“位置”)(“列表”)。map((“id”)
map(x=>x(“Locactions”)(“列表”)的快捷方式。map((“id”)
方法
map
转换容器的内部值(
Option
在本例中)使用给定函数。给定函数接收一个
Map
Map
并从中检索值(两层深)-它是包含id的映射列表。因此,
.Map(uU(“id”)
通过从每个元素(即
Map”)检索“id”值,将映射列表转换为id列表[String,String]
谢谢。不过看起来比其他答案更复杂。
net.liftweb.json
建议使用第三方库(我想是从Lift框架中)@FilipK:lift json是一个单独的包。你不必将整个lift框架拉入你的项目中。我对它很陌生。当然,一定有一种更简单的lift json方法来做你想做的事情。
import rapture.io._

// Let's parse some JSON
val src: Json = Json.parse("""
{
  "foo": "Hello world",
  "bar": {
    "baz": 42
  }
}
""")     

// We can now access the value bar.baz
val x: Json = src.bar.baz

// And get it as an integer
val y: Int = x.get[Int]

// Alternatively, we can use an extractor to get the values we want:
val json""" { "bar": { "baz": $x }, "foo": $z }""" = src

// Now x = 42 and z = "Hello world".
scala> import nl.typeset.sonofjson._
import nl.typeset.sonofjson._

scala> var all = obj(
     |   locations = arr(
     |     obj(description = "foo", id = "807",
     |     obj(description = "bar", id = "23324"
     |   )
     | )

scala> all.locations.map(_.id).as[List[String]]
res2: List[String] = List(23324, 807)
scala> (for (location <- all.locations) yield location.id).as[List[String]]
res4: List[String] = List(23324, 807)