gpt4 book ai didi

json - 解码json字符串里面的json

转载 作者:行者123 更新时间:2023-12-04 04:18:20 25 4
gpt4 key购买 nike

我正在处理 an 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,并打破编码器/解码器提供的抽象层。

有没有办法实现一个以一般方式进行双重解码的解码器?

最佳答案

好吧,因为所描述的 JSON 并不是真正的典型案例,我不确定是否有可能完全避免手动解析,但是如果您将更改表示此结构的案例类,您可以利用 circe 提供的一些优势。
请在下面找到代码示例:

import io.circe._
import io.circe.generic.semiauto._
import io.circe.generic.auto._

object CredentialsParseApp {
case class CredentialsBlob(access: String, secret: String)

object CredentialsBlob {

implicit val encoder: Encoder[CredentialsBlob] = {
val derivedEncoder: Encoder[CredentialsBlob] = deriveEncoder[CredentialsBlob]
Encoder[String].contramap(blob => derivedEncoder(blob).noSpaces)
}

implicit val decoder: Decoder[CredentialsBlob] = {
val derivedDecoder: Decoder[CredentialsBlob] = deriveDecoder[CredentialsBlob]
Decoder[String].emap { value =>
for {
json <- parser.parse(value).left.map(_.message)
blob <- json.as(derivedDecoder).left.map(_.message)
} yield blob
}
}
}

case class Credentials(blob: CredentialsBlob, project_id: String, `type`: String = "ec2", user_id: String)
case class Response(credential: Credentials)

def main(args: Array[String]): Unit = {
val jsonString =
"""{
| "credential": {
| "blob": "{\"access\": \"181920\", \"secret\": \"secretKey\" }",
| "project_id": "731fc6f265cd486d900f16e84c5cb594",
| "type": "ec2",
| "user_id": "bb5476fd12884539b41d5a88f838d773"
| }
|}""".stripMargin

println(parser.parse(jsonString).flatMap(_.as[Response]))
}
}

在我的情况下产生了下一个结果:
Right(Response(Credentials(CredentialsBlob(181920,secretKey),731fc6f265cd486d900f16e84c5cb594,ec2,bb5476fd12884539b41d5a88f838d773)))

我在这个例子中使用了 circe 版本“0.12.3”。希望这可以帮助!

关于json - 解码json字符串里面的json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60045035/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com