将Json转换为Map[String, String]

5

我有一个类似以下的JSON输入

{"a": "x", "b": "y", "c": "z", .... }

我想将这个json转换为一个类似于Map[String,String]的映射。
基本上是键值对的映射。
我该如何使用circe做到这一点?
请注意,我不知道Json中会出现哪些键“a”,“b”,“c”。 我只知道它们始终是字符串,而不是任何其他数据类型。
我在这里查看了自定义解码器https://circe.github.io/circe/codecs/custom-codecs.html,但它们仅适用于您知道标记名称的情况。
我在Jackson中找到了一个示例来完成此操作,但在circe中没有。
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.databind.ObjectMapper

val data = """
    {"a": "x", "b", "y", "c": "z"}
"""
val mapper = new ObjectMapper
mapper.registerModule(DefaultScalaModule)
mapper.readValue(data, classOf[Map[String, String]])
2个回答

12

其他答案中的解决方案虽然可行,但比必要的冗长。现成的circe提供一个隐式的Decoder[Map[String, String]]实例,因此你可以只需编写以下内容:

scala> val doc = """{"a": "x", "b": "y", "c": "z"}"""
doc: String = {"a": "x", "b": "y", "c": "z"}

scala> io.circe.parser.decode[Map[String, String]](doc)
res0: Either[io.circe.Error,Map[String,String]] = Right(Map(a -> x, b -> y, c -> z))

Decoder[Map[String, String]]实例是在Decoder伴生对象中定义的,因此它始终可用——您不需要任何导入、其他模块等。Circe为大多数标准库类型提供了合理的实例,例如,如果您想将JSON数组解码为List[String],则无需构建自己的Decoder[List[String]]——您可以直接使用来自Decoder伴生对象的隐式范围中的那个实例。

这不仅是解决此问题的更简洁的方式,而且也是推荐的解决方式。手动构造显式的解码器实例并从Either转换为Try以组合解析和解码操作既不必要,而且容易出错(如果确实需要最终得到TryOption或任何其他内容,则几乎肯定最好在最后执行)。


2
假设:

假设:

val rawJson: String = """{"a": "x", "b": "y", "c": "z"}"""

这个可以运行:

import io.circe.parser._

val result: Try[Map[String, String]] = parse(rawJson).toTry
  .flatMap(json => Try(json.asObject.getOrElse(sys.error("Not a JSON Object"))))
  .flatMap(jsonObject => Try(jsonObject.toMap.map{case (name, value) => name -> value.asString.getOrElse(sys.error(s"Field '$name' is not a JSON string"))}))

val map: Map[String, String] = result.get
println(map)

或者使用 Decoder:

import io.circe.Decoder

val decoder = Decoder.decodeMap(KeyDecoder.decodeKeyString, Decoder.decodeString)

val result = for {
  json <- parse(rawJson).toTry
  map <- decoder.decodeJson(json).toTry
} yield map

val map = result.get
println(map)

您可以尝试以下无效的输入并查看会抛出哪个异常:

val rawJson: String = """xxx{"a": "x", "b": "y", "c": "z"}""" // invalid JSON
val rawJson: String = """[1,2,3]""" // not a JSON object
val rawJson: String = """{"a": 1, "b": "y", "c": "z"}""" // not all values are string

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接