5

我想在我的案例类和 JSON 中使用不同的字段名称,因此我需要一种舒适的方式来重命名编码和解码。

有人有好的解决方案吗?

4

5 回答 5

3

您可以通过注释使用自定义键映射。最通用的方式是JsonKey注释来自io.circe.generic.extras._. 文档中的示例:

import io.circe.generic.extras._, io.circe.syntax._

implicit val config: Configuration = Configuration.default

@ConfiguredJsonCodec case class Bar(@JsonKey("my-int") i: Int, s: String)

Bar(13, "Qux").asJson
// res5: io.circe.Json = JObject(object[my-int -> 13,s -> "Qux"])

这需要包circe-generic-extras

于 2020-04-28T12:40:17.537 回答
2
implicit val decodeFieldType: Decoder[FieldType] =
  Decoder.forProduct5("nth", "isVLEncoded", "isSerialized", "isSigningField", "type")
                     (FieldType.apply)

This is a simple way if you have lots of different field names. https://circe.github.io/circe/codecs/custom-codecs.html

于 2019-04-04T05:18:30.487 回答
2

这是解码器的代码示例(有点冗长,因为它不会删除旧字段):

  val pimpedDecoder = deriveDecoder[PimpClass].prepare {
    _.withFocus {
      _.mapObject { x =>
        val value = x("old-field")
        value.map(x.add("new-field", _)).getOrElse(x)
      }
    }
  }
于 2017-03-10T14:45:48.063 回答
1

您可以使用 Encoder 上的mapJson函数从通用编码器派生编码器并重新映射您的字段名称。

您可以使用解码器上的prepare函数将传递给通用解码器的 JSON 转换。

你也可以从头开始写,但它可能是大量的样板文件,这些解决方案都应该是每个最多几行。

于 2016-11-07T16:36:43.487 回答
1

以下函数可用于重命名 circe 的 JSON 字段:

import io.circe._

object CirceUtil {
  def renameField(json: Json, fieldToRename: String, newName: String): Json =
    (for {
      value <- json.hcursor.downField(fieldToRename).focus
      newJson <- json.mapObject(_.add(newName, value)).hcursor.downField(fieldToRename).delete.top
    } yield newJson).getOrElse(json)
}

您可以Encoder像这样使用它:

implicit val circeEncoder: Encoder[YourCaseClass] = deriveEncoder[YourCaseClass].mapJson(
  CirceUtil.renameField(_, "old_field_name", "new_field_name")
)

额外的

单元测试

import io.circe.parser._
import org.specs2.mutable.Specification

class CirceUtilSpec extends Specification {

  "CirceUtil" should {
    "renameField" should {
      "correctly rename field" in {
        val json = parse("""{ "oldFieldName": 1 }""").toOption.get
        val resultJson = CirceUtil.renameField(json, "oldFieldName", "newFieldName")
        resultJson.hcursor.downField("oldFieldName").focus must beNone
        resultJson.hcursor.downField("newFieldName").focus must beSome
      }

      "return unchanged json if field is not found" in {
        val json = parse("""{ "oldFieldName": 1 }""").toOption.get
        val resultJson = CirceUtil.renameField(json, "nonExistentField", "newFieldName")
        resultJson must be equalTo json
      }
    }
  }
}
于 2021-05-07T12:06:56.063 回答