scala解析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,

当我解析它返回结构时,我有一些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, 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,它仍将匹配第一种情况。哎呀,我总是忘记类型擦除。(即在选项上匹配,然后在列表上匹配,然后在地图上匹配等)将是最好的。