考虑一下这个JSON:

{
  "myDocument": {
    "static_key": "value",
    "dynamic_key": "value",
    "static_key2": "value2",
    "dynamic_key2": {
      "dynamic_key3": "value3"
    }
  }
}

我将要处理的JSON文档有一些静态密钥(我知道将永远存在的字段)但是有一些可能存在或不存在的字段,事先不知道名称将它们映射到某些 case class .

我有一个String的字段的绝对路径(从存储在数据库中的配置中检索)具有以下结构:

"myDocument.dynamic_key2.dynamic_key3"

我知道我需要有一个ADT来回映射,所以我来到这里:

sealed trait Data

final case class StringTuple(key: String, value: String) extends Data

object StringTuple {

  implicit val encoder: Encoder[StringTuple] = deriveEncoder[StringTuple]
  implicit val decoder: Decoder[StringTuple] = deriveDecoder[StringTuple]
}

final case class NumericTuple(key: String, value: Double) extends Data

object NumericTuple {

  implicit val encoder: Encoder[NumericTuple] = deriveEncoder[NumericTuple]
  implicit val decoder: Decoder[NumericTuple] = deriveDecoder[NumericTuple]
}

final case class DateTuple(key: String, value: OffsetDateTime) extends Data

object DateTuple {

  implicit val encoder: Encoder[DateTuple] = deriveEncoder[DateTuple]
  implicit val decoder: Decoder[DateTuple] = deriveDecoder[DateTuple]
}

final case class TransformedJson(data: Data*)

object TransformedJson {

  def apply(data: Data*): TransformedJson = new TransformedJson(data: _*)

  implicit val encoder: Encoder[TransformedJson] = deriveEncoder[TransformedJson]
  implicit val decoder: Decoder[TransformedJson] = deriveDecoder[TransformedJson]
}

基于这个discussion,将 Map[String, Any] 与circe一起使用是没有意义的,所以我将解析各个字段时遇到的三个可能的键值情况分开:

  • 一个数字字段,我要解析为 Double .

  • 按字符串字段解析( String ) .

  • 解析为 OffsetDateTime 的日期字段 .

出于这个原因,我创建了三个案例类来模拟这些组合( NumericTupleStringTupleDateTuple ),我的想法是生成这样的输出JSON:

{
  "dynamic_key": "extractedValue",
  "dynamic_key3": "extractedValue3",
  ...
}

(“平原”,完全没有嵌套) .

我的想法是创建一个 Data 对象列表来实现这一点,我有这样的事情:

def extractValue(confElement: Conf, json: String) = {
    val cursor: HCursor = parse(json).getOrElse(Json.Null).hcursor
    val decodeDynamicParam = Decoder[NumericTuple].prepare(
      /*
          Here I think (not sure) that I can extract the value with the decoder,
          but, how can I extract the key name and set it, alongside with the extracted
          value?
       */
      _.downField(confElement.path)
    )
  }

Some considerations:

Question: 如何提取当前光标位置的特定键名并将其映射到 Tuple ?我只需要当前的键,而不是 ACursor.keys 方法返回的所有键集 . 使用该键,我想手动映射具有当前键名和提取值的元组 .

为了总结它,我需要转换一个具有一些未知键(名称和位置)的结构,根据我拥有的绝对点分隔路径提取它们的值,并将键名和值名称提升为a case类,我后缀为 Tuple .

你能解释一下吗?

谢谢