I have a JSON that looks like:
{
"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
}
]
}
I am mainly interested in parsing/deserializing the data list, and I would like to do that manually (I prefer the manual way for some mysterious reason).
In case this is relevant, I am using sttp's circe library sttp.client.circe._
with the intention of parsing incoming data from get requests directly into Json using asJson
.
A get sttp request looks something like:
val r1 = basicRequest
.get(uri"https://woooo.woo.wo/v1/users")
.header("accept", "application/json")
.header("Authorization", "topsecret"
.response(asJson[SomeClass])
This is what I have tried so far:
// 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)
}
}
The problem with my approach (I think) is that .downArray
makes me only serialize the first User in the array of Users.
My objective is to be able to have some sequence of users (something like List[User]
maybe), but at the moment I only end up deserializing one user in the array.
It is worth mentioning that the "data" array, does not contain a fixed-number of users, and every api call could result in a different number of users.