scala解析json,其中包含映射列表
当我解析它返回结构时,我有一些json(列表(映射…) 如何匹配某个对象并获取值 下面是我试过的代码,我需要得到所有的映射值scala解析json,其中包含映射列表,json,scala,Json,Scala,当我解析它返回结构时,我有一些json(列表(映射…) 如何匹配某个对象并获取值 下面是我试过的代码,我需要得到所有的映射值 import scala.util.parsing.json._ val result = JSON.parseFull("[{\"start\":\"starting\",\"test\":123,\"test2\":324,\"end\":\"ending\"}]") result match { case Some(map: Map[String,
import scala.util.parsing.json._
val result = JSON.parseFull("[{\"start\":\"starting\",\"test\":123,\"test2\":324,\"end\":\"ending\"}]")
result match {
case Some(map: Map[String, Any]) => { println(map)
}
case None => println("Parsing failed")
case other => println("Unknown data structure: " + other)
}
但它的打印不匹配
Unknown data structure: Some(List(Map(start -> starting, test -> 123, test2 -> 324, end -> ending)))
您的输出是
选项[List[Map[String,Any]]]
,而不是选项[Map[String,Any]]
。在列表中匹配,您将很好:
import scala.util.parsing.json._
val result = JSON.parseFull("[{\"start\":\"starting\",\"test\":123,\"test2\":324,\"end\":\"ending\"}]")
val l: List[Map[String, Any]] = result match {
case Some(list: List[Map[String, Any]]) => list
case _ => throw new Exception("I shouldn't be here") // whatever for a non-match
}
然后,您可以在该列表上映射(如果您想要非单位退货类型)/foreach
(如果您不关心单位退货类型),并执行您想要的任何操作:
l.foreach(println)
l.map(_.toString) // or whatever you want ot do with the Map
正如已经指出的那样,返回类型实际上是
选项[List[Map[String,Any]]]
,因此您需要取消选中该选项。但是,由于类型擦除,无法使用单个匹配执行此操作,因此需要执行嵌套匹配以确保具有正确的类型。这真的很乏味,所以我完全建议使用json4s
中的Extraction.extract
函数,尝试将JSON与特定的Scala类型匹配:
type ResultType = List[Map[String, Any]]
def extract(json: JValue)(implicit formats: Formats, mf: Manifest[ResultType]): ResultType =
Extraction.extract[ResultType](json)
如果您必须手工操作,它看起来是这样的:
result match {
case Some(l: List[_]) =>
l.headOption match {
case Some(m) =>
m match {
case m: Map[_,_] =>
m.headOption match {
case Some(p) =>
p match {
case (_: String, _) =>
m.foreach(println(_))
case _ => println("Map key was not String")
}
case _ => println("Map was empty")
}
case _ => println("List did not contain a Map")
}
case _ => println("Result List was empty")
}
case _ => println("Parsing failed")
}
由于类型擦除,您无法在泛型类型上进行模式匹配<代码>列表
,映射
,选项
是通用容器,运行时编译器将删除这些通用容器的类型。e、 g.List[String]
,String
将被擦除,类型将为List[\u]
case Some(map: List[Map[String, Any]]) => println(map)
在上面的例子中,如果结果是valresult:Option[Any]=Some(List(12))
,即12
,类型是Int
,而不是Map[String,Any]
,编译器仍然将结果与上面的例子匹配,即使它期望Map[String,Any]
作为列表的类型
那么,发生了什么事?
这都是因为类型擦除。编译器将删除所有类型,并且在运行时不会有任何类型信息,除非您使用反射。这意味着:
case-Some(map:List[map[String,Any]]=>println(map)
本质上是case-Some(map:List[])=>println(map)
,因此,匹配List
的任何类型参数都会成功,例如List[map[String,Any]
,List[map[String,Int]
,List[String]
,List[String]
,List[Int]
等
因此,如果需要在此类泛型容器上进行匹配,则必须显式解析每个容器及其嵌套子类型
def resolve(result: Any): Unit = result match {
case Some(res) if res.isInstanceOf[List[_]] && res.asInstanceOf[List[_]].isEmpty => println("Empty List.") //Some(List())
case Some(res) if res.isInstanceOf[List[_]] && !res.asInstanceOf[List[_]].exists(p => p.isInstanceOf[Map[_, _]] && p.asInstanceOf[Map[_, _]].nonEmpty) => println("List is not empty but each item of List is empty Map.") //Some(List(Map(), Map()))
case Some(res) if res.isInstanceOf[List[_]] && res.asInstanceOf[List[_]].filter(p => p.isInstanceOf[Map[_, _]] && p.asInstanceOf[Map[_, _]].nonEmpty).map(_.asInstanceOf[Map[_,_]]).exists(p => {p.head match {case e if e._1.isInstanceOf[String] && e._2.isInstanceOf[Any] => true; case _ => false}}) => println("Correct data.") // Some(List(Map("key1"-> 1), Map("key2" -> 2)))
case None => println("none")
case other => println("other")
}
val a: Option[Any] = Some(List())
val b: Option[Any] = Some(List(Map(), Map()))
val c: Option[Any] = Some(List(Map("key1"-> 1), Map("key2" -> 2)))
val d: Option[Any] = None
val e: Option[Any] = Some("apple")
resolve(a) // match first case
resolve(b) // match second case
resolve(c) // match third case
resolve(d) // match fourth case
resolve(e) // match fifth case
您输入的是JSON.parseFull
的预期结果。例如,JSON是一个数组,它将被解析为列表
,然后被解析为数组内对象的映射
。要添加到@AndrewNolan,下面是模式匹配的方式:result match{case Some(List(m:Map[,])=>println(m)}如何迭代该列表以获取映射对象。这是模式匹配通用容器避免类型擦除的最佳方法。这不起作用。e、 g.val result:Option[List[Any]]=Some(List(1))
由于类型擦除,即使1不是Int-Map,它仍将匹配第一种情况。哎呀,我总是忘记类型擦除。(即在选项上匹配,然后在列表上匹配,然后在地图上匹配等)将是最好的。