1

我想创建一个带有 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)
4

2 回答 2

2

好的,快速修复是使用 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
),
于 2017-10-04T11:02:11.983 回答
1

您只需要提供一个Encoderin 范围内的隐式实例 for Object。试试这个:

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

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

Encoder.instancePS:如果您使用的是 Scala 版本 >= 2.12.0,由于重载分辨率中的 SAM 转换,您可以避免打字。所以代码会变成:

implicit val objEncoder: Encoder[Object] = {
  case x: String => x.asJson
  case xs: List[Map[String, String]] => xs.asJson
}
于 2017-10-04T10:01:24.770 回答