【问题标题】:Generic Json Parsing in ScalaScala中的通用Json解析
【发布时间】:2017-01-24 11:00:52
【问题描述】:

我有一个通用 JSON,其中所有键和值都是字符串。

示例 1:

[
  {
    "key1": "value1"
  },
  {
    "key1": "value2"
  }
]

但 JSON 也可以是: 例 2:

[
  {
    "key1": "value1",
    "key2": "value2"
  },
  {
    "key1": "value3",
    "key2": "value4"
  }
]

我想将 JSON 转换为 Map。 示例 1 将转换为 Map[String, String]

示例 2 将转换为 List[Map[String, String]]

所以基本上我想将 JSON 转换为 Map 并按如下方式使用它:

map("key1")("key2")("key3")

得到最终的结果值3。

请帮忙!!

【问题讨论】:

  • 这些示例都不是有效的 JSON(您可以在此处亲自查看:jsonformatter.curiousconcept.com
  • map("key1")("key2")("key3") 返回value3???那个怎么样? key3 哪里来的??
  • 它是一个通用的 'json'。你只能有一个键或n个键。我想将 'json' 转换为嵌套地图并想获取 map(k1)(k2)..(kn)

标签: json scala jackson json4s


【解决方案1】:

使用play-json,您可以使用validate 将Json 转换为Map。验证返回 JsResult,它可以是 JsSuccess(data,path)JsError(errors)。模式匹配以从中获取地图。

如果不回退到案例 2,则检查 str 是否属于案例 1

Json.parse(jsonString).validate[Map[String, String]].getOrElse(json.validate[List[Map[String,String]]])

案例 1:对于 Map[String, String]

import play.api.libs.json._
val result = Json.parse(someValidJsonString).validate[Map[String, String]]
result match {
  case JsSuccess(map, _) => map
  case JsError(errors) => Logger.error("json parsing failed")
}

案例 2:对于 List[Map[String, String]]

import play.api.libs.json._
    val result = Json.parse(someValidJsonString).validate[List[Map[String, String]]]
    result match {
      case JsSuccess(list, _) => list
      case JsError(errors) => Logger.error("json parsing failed")
    }

这里someValidJsonString是你要转成Map的json字符串

如果您使用的是sbt project,则将play-json 依赖项添加到您的项目中。

build.sbt

libraryDependencies ++= Seq("com.typesafe.play" %% "play-json" % "2.5.4")

Scala REPL

scala> import play.api.libs.json._
import play.api.libs.json._

scala> val map = Map("java" -> 1, "scala" -> 2)
map: scala.collection.immutable.Map[String,Int] = Map(java -> 1, scala -> 2)

scala> Json.toJson(map).validate[Map[String, Int]]
res3: play.api.libs.json.JsResult[Map[String,Int]] = JsSuccess(Map(java -> 1, scala -> 2),)

scala> val result = Json.toJson(map).validate[Map[String, Int]]
result: play.api.libs.json.JsResult[Map[String,Int]] = JsSuccess(Map(java -> 1, scala -> 2),)

scala> result match { case JsSuccess(data, _) => data case JsError(errors) => Unit}
res4: Object = Map(java -> 1, scala -> 2)

【讨论】:

  • 挑战不仅仅是将 JSON 转换为地图,它的嵌套部分因此 1 'json' 可以是 {{'k1': 'v1'}, {'k1':'v2'}} 即所有条目都有 1 个元素,但其他可以是 {{k1:v1, k2:v2}, {k1:v3, k2:v4} } 所以对于案例 1 我需要 Map[String, String] 但对于案例 2 我需要 Map[字符串,地图[字符串,字符串]]
  • @satendra 你知道case 2什么时候出现
  • 我正在尝试为用户将文件放在平台上并且系统将其条目存储到“json”中的 db 的场景编写代码,具体取决于列数,其中的条目数每个单独的“json”,但它们始终是字符串,因此 example1 对应于 1 列文件,example2 对应于具有 2 列的文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多