在Scala中将JSON转换为MultiMap

时间:2015-12-30 21:48:10

标签: json scala playframework

我正在使用 Scala 播放。我有一个 JSON 文件,其中包含世界上所有国家/地区及其各自的城市。 JSON看起来像这样:

{
    "CountryA": ["City1","city2"],
    "CountryB": ["City1"]
}

我会相应地解析它:

val source: String = Source.fromFile("app/assets/jsons/countriesToCities.json").getLines.mkString
val json: JsValue = Json.parse(source)

我的最终目标是将json内容转换为Scala MultiMap ,其中String - 国家/地区Set[String] - cities

提前致谢!

1 个答案:

答案 0 :(得分:2)

这是一个冗长的解决方案,如果JSON结构与您期望的不匹配,则不会抛出:

  val source: String =
    """
      |{
      |    "CountryA": ["City1","city2"],
      |    "CountryB": ["City1"]
      |}
    """.stripMargin

  val json: JsValue = Json.parse(source)

  import scala.collection.breakOut

  val map: Map[String, Set[String]] = json.asOpt[JsObject] match {
    case Some(obj) =>
      obj.fields.toMap.mapValues { v =>
        v.asOpt[JsArray] match {
          case Some(JsArray(cities)) => cities.flatMap(_.asOpt[String])(breakOut)
          case _ => Set.empty[String]
        }
      }
    case _ => Map.empty[String, Set[String]]
  }

  map must beEqualTo(Map("CountryA" -> Set("City1", "city2"), "CountryB" -> Set("City1")))

如果您对JSON的结构有信心并且不介意使用as(可以抛出)而不是asOpt(不会):

  val map2: Map[String, Set[String]] = {
    json.as[JsObject].fields.toMap.mapValues {
      _.as[JsArray].value.map(_.as[String])(breakOut)
    }
  }

  map2 must beEqualTo(Map("CountryA" -> Set("City1", "city2"), "CountryB" -> Set("City1")))