将Json转换为Map [String,String]

时间:2019-01-05 04:51:41

标签: json scala circe

我输入了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处查看了自定义解码器,但是它们仅在您知道标签名称时才起作用。

我在杰克逊(Jackson)找到了一个做到这一点的例子。但不是大约

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 个答案:

答案 0 :(得分:4)

虽然其他答案中的解决方案有效,但它们比必要的更为冗长。现成的圈子提供了一个隐式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]]-您可以仅使用{{1 }}随播对象。

这不仅是解决此问题的详细方法,而且是解决此问题的推荐方法。手动构造一个显式的解码器实例并将其从Decoder转换为Either以进行解析和解码操作既不必要又容易出错(如果您需要以Try或{{ 1}}或其他任何一种方法,几乎​​可以肯定的是,最好在最后进行操作。

答案 1 :(得分:1)

假设:

@Override
public void onClick(View v) {
    Car car = mCars.get(getAdapterPosition());
    mListCallBack.onCarSelected(car);
}

这有效:

setContentView(R.layout.main);

或使用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