Scala 如何使用Circe'反序列化非固定JSON数组;什么是手动解码器?
我有一个JSON,看起来像:Scala 如何使用Circe'反序列化非固定JSON数组;什么是手动解码器?,scala,circe,sttp,Scala,Circe,Sttp,我有一个JSON,看起来像: { "data": [ { "id": "1", "email": "hello@world.com", "name": "Mr foo", "roles": [ "Chief Bar Officer"
{
"data": [
{
"id": "1",
"email": "hello@world.com",
"name": "Mr foo",
"roles": [
"Chief Bar Officer"
],
"avatar_url": null,
"phone_number": null
},
{
"id": "2",
"email": "bye@world.com",
"name": "Mr baz",
"roles": [
"Chief Baz Officer"
],
"avatar_url": null,
"phone_number": null
}
]
}
我主要对解析/反序列化数据列表感兴趣,我希望手动完成(出于某种神秘的原因,我更喜欢手动方式)
如果这是相关的,我将使用sttp的circe库sttp.client.circe.\uu
,目的是使用asJson
将get请求中的传入数据直接解析为Json
get sttp请求类似于:
val r1 = basicRequest
.get(uri"https://woooo.woo.wo/v1/users")
.header("accept", "application/json")
.header("Authorization", "topsecret"
.response(asJson[SomeClass])
case class Users(users: List[User])
case object User {
implicit val usrDecoder: Decoder[User] = (hCursor: HCursor) => {
for {
id <- hCursor.get[String]("id")
email <- hCursor.get[String]("email")
name <- hCursor.get[String]("name")
roles <- hCursor.get[List[String]]("roles")
avatarUrl <- hCursor.get[Option[String]]("avatarUrl")
phoneNumber <- hCursor.get[Option[String]]("phoneNumber")
} yield User(id, email, name, roles, avatarUrl, phoneNumber)
}
implicit val decodeUsers: Decoder[Users] =
Decoder[List[User]].at("data").map(Users)
}
json.as[Data[List[User]]]
这就是我迄今为止所尝试的:
// Define the case class
case class User(
id: String,
email: String,
name: String,
roles: List[String],
avatar_url: Option[String],
phone_number: Option[String]
)
// Define the manual deserializer
case object User {
implicit val userDecoder: Decoder[User] = (hCursor: HCursor) => {
val data = hCursor.downField("data").downArray
for {
id <- data.get[String]("id")
email <- data.get[String]("email")
name <- data.get[String]("name")
roles <- data.get[List[String]]("roles")
avatarUrl <- data.get[Option[String]]("avatarUrl")
phoneNumber <- data.get[Option[String]]("phoneNumber")
} yield User(id, email, name, roles, avatarUrl, phoneNumber)
}
}
//定义案例类
案例类用户(
id:String,
电子邮件:String,
名称:String,
角色:列表[字符串],
头像url:选项[字符串],
电话号码:选项[字符串]
)
//定义手动反序列化程序
案例对象用户{
隐式val userDecoder:Decoder[User]=(hCursor:hCursor)=>{
val data=hCursor.downField(“数据”).downArray
为了{
我感谢和的帮助,谢谢你帮我解决了这个问题
我在这里引用特拉维斯的话:
最好是建立您需要的实例来解析
顶级JSON对象的组成…即有一个解码器[用户]可以
仅解码单个用户JSON对象,然后使用
解码器[列表[用户])。位于(“数据”)或类似于解码
包含数据字段和JSON数组的顶级JSON对象
我最终得到了一个类似以下内容的实现:
val r1 = basicRequest
.get(uri"https://woooo.woo.wo/v1/users")
.header("accept", "application/json")
.header("Authorization", "topsecret"
.response(asJson[SomeClass])
case class Users(users: List[User])
case object User {
implicit val usrDecoder: Decoder[User] = (hCursor: HCursor) => {
for {
id <- hCursor.get[String]("id")
email <- hCursor.get[String]("email")
name <- hCursor.get[String]("name")
roles <- hCursor.get[List[String]]("roles")
avatarUrl <- hCursor.get[Option[String]]("avatarUrl")
phoneNumber <- hCursor.get[Option[String]]("phoneNumber")
} yield User(id, email, name, roles, avatarUrl, phoneNumber)
}
implicit val decodeUsers: Decoder[Users] =
Decoder[List[User]].at("data").map(Users)
}
json.as[Data[List[User]]]
案例类用户(用户:列表[用户])
案例对象用户{
隐式val-usrDecoder:Decoder[用户]=(hCursor:hCursor)=>{
为了{
id如果您想解码列表[用户]
您需要为确切的类型列表[用户]
创建解码器。它可能看起来像:
implicit val userDecoder: Decoder[List[User]] = (hCursor: HCursor) => {
Either.fromOption(
hCursor.downField("data").values,
DecodingFailure("Can't decode data", Nil)
).flatMap { values =>
values.toList.map(_.hcursor).traverse {
userCursor =>
for {
id <- userCursor.get[String]("id")
email <- userCursor.get[String]("email")
name <- userCursor.get[String]("name")
roles <- userCursor.get[List[String]]("roles")
avatarUrl <- userCursor.get[Option[String]]("avatarUrl")
phoneNumber <- userCursor.get[Option[String]]("phoneNumber")
} yield User(id, email, name, roles, avatarUrl, phoneNumber)
}
}
}
这可能不是最好的主意,因为circe已经可以将json数组解码到列表中,所以最好只为用户创建解码器(解码对象):
另一种可能是只为数据
包装器创建case类:
case class Data[D](data: D)
object Data {
implicit def dataDecoder[D: Decoder]: Decoder[Data[D]] =
(hCursor: HCursor) => hCursor.get[D]("data").map(Data(_))
}
然后,您可以执行以下操作:
val r1 = basicRequest
.get(uri"https://woooo.woo.wo/v1/users")
.header("accept", "application/json")
.header("Authorization", "topsecret"
.response(asJson[SomeClass])
case class Users(users: List[User])
case object User {
implicit val usrDecoder: Decoder[User] = (hCursor: HCursor) => {
for {
id <- hCursor.get[String]("id")
email <- hCursor.get[String]("email")
name <- hCursor.get[String]("name")
roles <- hCursor.get[List[String]]("roles")
avatarUrl <- hCursor.get[Option[String]]("avatarUrl")
phoneNumber <- hCursor.get[Option[String]]("phoneNumber")
} yield User(id, email, name, roles, avatarUrl, phoneNumber)
}
implicit val decodeUsers: Decoder[Users] =
Decoder[List[User]].at("data").map(Users)
}
json.as[Data[List[User]]]