从 Circe 创建 Json 对象,值可以是字符串或列表

Create Json object from Circe where the value can be String or a List

我想用 circe 创建一个 Json 对象,其中值可以是字符串或列表,例如:

val param = Map[String, Map[String, Object]](
    "param_a" -> Map[String, Object](
      "param_a1" -> "str_value",
      "param_a2" -> List(
        Map[String, String](
          "param_a2.1" -> "value_2.1",
          "param_a2.2" -> "value_2.2")
      )
    ),

但是,如果我这样做

    param.asJson

失败

    Error:(61, 23) could not find implicit value for parameter encoder: io.circe.Encoder[scala.collection.immutable.Map[String,Map[String,Object]]]
  .postData(param.asJson.toString().getBytes)

您只需在 Object 的范围内提供 Encoder 的隐式实例。试试这个:

implicit val objEncoder: Encoder[Object] = Encoder.instance {
  case x: String => x.asJson
  case xs: List[Map[String, String]] => xs.asJson
}

但是我会避免使用 Object,而是提供一个 ADT 来包装两种可能的情况,即 StringList[Map[String, String]],但这取决于您。此外,在 Scala 世界中,Object 更广为人知的是 AnyRef,因此如果您只想使用 Object,我建议您将其称为 AnyRef.

P.S.: 如果你使用 Scala 版本 >= 2.12.0 你可以避免输入 Encoder.instance 感谢 SAM conversion in overloading resolution。所以代码会变成:

implicit val objEncoder: Encoder[Object] = {
  case x: String => x.asJson
  case xs: List[Map[String, String]] => xs.asJson
}

好的,一个快速解决方法是使用 Map[String, Json]

val param = Map[String, Map[String, Json]](
"param_a" -> Map[String, Json](
  "param_a1" -> "str_value".asJson,
  "param_a2" -> List(
    Map[String, String](
      "param_a2.1" -> "value_2.1",
      "param_a2.2" -> "value_2.2")
  ).asJson
),