Я имею дело с API , который ожидает объект JSON, где одно из значений (blob) является JSON строковым объектом:
{
"credential": {
"blob": "{\"access\":\"181920\",\"secret\":\"secretKey\"}",
"project_id": "731fc6f265cd486d900f16e84c5cb594",
"type": "ec2",
"user_id": "bb5476fd12884539b41d5a88f838d773"
}
}
Мой домен класс:
case class Credential(access: String, secret: String, projectId: String, userId: String)
Кодирование класса домена легко:
implicit val encoder: Encoder[Credential] = (a: Credential) => Json.obj(
"type" -> "ec2".asJson,
"blob" -> Map("access" -> a.access, "secret" -> a.secret).asJson.noSpaces.asJson,
"project_id" -> a.projectId.asJson,
"user_id" -> a.userId.asJson
)
Однако декодирование намного сложнее:
implicit val decoder: Decoder[Credential] = (c: HCursor) => for {
blobJsonString <- c.get[String]("blob")
blob <- decode[Json](blobJsonString).left.map(e => DecodingFailure(e.getMessage, c.downField("blob").history))
access <- blob.hcursor.get[String]("access")
secret <- blob.hcursor.get[String]("secret")
projectId <- c.get[String]("project_id")
userId <- c.get[String]("user_id")
} yield Credential(access, secret, projectId, userId)
Мне не нравится эта реализация потому что это заставляет меня зависеть от circe-parser и нарушать уровень абстракции, предоставляемый кодерами / декодерами.
Есть ли способ реализовать декодер, который выполняет двойное декодирование обычным способом?