【问题标题】:Convert Json to a Map[String, String]将 Json 转换为 Map[String, String]
【发布时间】:2019-05-31 14:58:46
【问题描述】:

我输入了类似的json

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

我想将此 json 转换为 Map[String, String] 之类的 Map

所以基本上是键值对的映射。

如何使用 circe 做到这一点?

请注意,我不知道 Json 中会出现哪些键“a”、“b”、“c”。我所知道的是,它们将永远是字符串,而不是任何其他数据类型。

我在这里查看了自定义解码器https://circe.github.io/circe/codecs/custom-codecs.html,但它们仅在您知道标签名称时才起作用。

我在杰克逊找到了一个例子。但不在循环中

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]])

【问题讨论】:

    标签: json scala circe


    【解决方案1】:

    虽然其他答案中的解决方案有效,但它们比必要的要冗长得多。现成的 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
      

      【讨论】:

        猜你喜欢
        • 2016-07-29
        • 2013-05-24
        • 2014-01-29
        • 1970-01-01
        • 1970-01-01
        • 2016-07-21
        • 1970-01-01
        • 2015-11-21
        • 1970-01-01
        相关资源
        最近更新 更多