斯卡拉解析JSON的地图列表

时间:2018-09-28 01:04:07

标签: json scala

当我解析它返回结构Some(List(Map ...))

时,我有一些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)))

3 个答案:

答案 0 :(得分:2)

正如已经指出的,返回类型实际上是Option[List[Map[String, Any]]],因此您需要取消选择。但是,由于类型擦除,您不能使用单个match来执行此操作,因此您需要进行嵌套匹配以确保您具有正确的类型。这确实很繁琐,所以我强烈建议在Extraction.extract中使用类似json4s函数的方法,该函数将尝试将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")
}

答案 1 :(得分:2)

由于类型擦除,您无法对通用类型进行模式匹配。 JavaScriptListMap是通用容器,在运行时编译器将擦除这些通用容器的类型。例如OptionList[String]将被删除,类型将为String

List[_]

在上述情况下,如果结果为case Some(map: List[Map[String, Any]]) => println(map) ,即val result: Option[Any] = Some(List(12)),其类型为12而不是Int,则编译器仍将匹配Map[String, Any]在上述情况下,甚至期望resultMap[String, Any]]的类型。

那么,怎么回事?

这都是由于类型擦除所致。除非您使用反射,否则编译器将擦除所有类型,并且在运行时不会包含任何类型信息。这意味着: List本质上是case Some(map: List[Map[String, Any]]) => println(map),因此,对于case Some(map: List[_]) => println(map)的任何类型参数(例如, ListList[Map[String, Any]]List[Map[String, Int]]List[String]等。

因此,如果需要在此类通用容器上进行匹配,则必须显式解析每个容器及其嵌套的子类型。

List[Int]

答案 2 :(得分:-2)

您的输出是Option[List[Map[String, Any]]],而不是Option[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
}

然后,您可以在该列表上map(如果要使用非单位返回类型)/ foreach(如果您不在乎单位返回类型)并执行所需的操作:

l.foreach(println)
l.map(_.toString) // or whatever you want ot do with the Map