다음과 같은 JSON이 있습니다.
{
"data": [
{
"id": "1",
"email": "[email protected]",
"name": "Mr foo",
"roles": [
"Chief Bar Officer"
],
"avatar_url": null,
"phone_number": null
},
{
"id": "2",
"email": "[email protected]",
"name": "Mr baz",
"roles": [
"Chief Baz Officer"
],
"avatar_url": null,
"phone_number": null
}
]
}
저는 주로 데이터 목록을 구문 분석 / 역 직렬화하는 데 관심이 있으며 수동으로 수행하고 싶습니다 (신비한 이유로 수동 방식을 선호합니다).
이것이 관련이있는 경우, 나는 .NET을 sttp.client.circe._
사용하여 Json으로 직접 get 요청에서 들어오는 데이터를 구문 분석 할 목적으로 sttp의 circe 라이브러리 를 사용하고 asJson
있습니다.
get sttp 요청은 다음과 같습니다.
val r1 = basicRequest
.get(uri"https://woooo.woo.wo/v1/users")
.header("accept", "application/json")
.header("Authorization", "topsecret"
.response(asJson[SomeClass])
이것이 내가 지금까지 시도한 것입니다.
// 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)
}
}
내 접근 방식의 문제는 (내 생각에) .downArray
사용자 배열에서 첫 번째 사용자 만 직렬화 한다는 것 입니다.
내 목표는 일련의 사용자 ( List[User]
아마도 비슷한 것) 를 가질 수 있도록하는 것이지만, 현재는 배열에서 한 사용자 만 역 직렬화합니다.
"데이터"배열은 고정 된 수의 사용자를 포함하지 않으며 모든 api 호출로 인해 사용자 수가 다를 수 있다는 점을 언급 할 가치가 있습니다.
이 문제를 해결하는 데 도움을 준 Travis Brown 과 circe Gitter 커뮤니티 의 도움에 감사드립니다 .
여기서 Travis를 인용합니다.
최상위 JSON 객체를 구성 적으로 구문 분석하는 데 필요한 인스턴스를 구축하는 것이 좋습니다. 즉, 단일 사용자 JSON 객체 만 디코딩하는 Decoder [User]가 있고 Decoder [List [User]]. at (를 사용합니다. "data") 또는 JSON 배열로 데이터 필드를 포함하는 최상위 JSON 객체를 디코딩하는 것과 유사한 것입니다.
나는 다음과 같은 구현으로 끝났습니다.
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)
}
아이디어는 사용자의 디코더와 사용자 모음에 대한 디코더를 별도로 구성하는 것입니다. 그런 다음 Users
Decoder 에 매핑 하여 Decoder의 결과를 Users 케이스 클래스로 래핑합니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다