scala play 读取解析嵌套 json
scala play reads parse nested json
我正在使用 implicit val reads
来映射 Json,例如:
{
"id": 1
"friends": [
{
"id": 1,
"since": ...
},
{
"id": 2,
"since": ...
},
{
"id": 3,
"since": ...
}
]
}
一个案例class
case class Response(id: Long, friend_ids: Seq[Long])
我只能让它与反映 JSON friends
结构的中间 class 一起工作。但我从不在我的应用程序中使用它。有没有一种方法可以编写一个 Reads[Response]
对象,以便我的响应 class 可以直接映射到给定的 JSON?
您可以尝试以下方法
@annotation.tailrec
def go(json: Seq[JsValue], parsed: Seq[Long]): JsResult[Seq[Long]] =
json.headOption match {
case Some(o @ JsObject(_)) => (o \ "id").validate[Long] match {
case JsError(cause) => JsError(cause)
case JsSuccess(id) => go(json.tail, parsed :+ id)
}
case Some(js) => JsError(s"invalid friend JSON (expected JsObject): $js")
case _ => JsSuccess(parsed) // nothing more to read (success)
}
implicit val friendIdReader = Reads[Seq[Long]] {
case JsArray(values) => go(values, Nil)
case json => JsError(s"unexpected JSON: $json")
}
implicit val responseReader = Json.reads[Response]
// responseReader will use friendIdReader as Reads[Seq[Long]],
// for the property friend_ids
简单的方法可能是:
import play.api.libs.functional.syntax._
import play.api.libs.json.{JsValue, Json, _}
case class Response(id: Long, friend_ids: Seq[Friends])
object Response {
implicit val userReads: Reads[Response] = (
(JsPath \ "id").read[Long] and
(JsPath \ "friends").read[Seq[Friends]]
) (Response.apply _)
}
case class Friends(id: Long, since: String)
object Friends {
implicit val fmt = Json.format[Friends]
}
没有 case class Friends
我发现很难找到解决方案,但 post 如果我能找到
Edit: Added link for answer on Scala reedit
所以,我想进一步了解如何将 json 解析为模型,并决定在 Reedit 上提问。收到了一些很酷的链接,看看:
https://www.reddit.com/r/scala/comments/4bz89a/how_to_correctly_parse_json_to_scala_case_class/
您只需要对 friend_ids
进行显式 Reads.seq()
的简单读取[响应],例如
val r: Reads[Response] = (
(__ \ "id").read[Long] and
(__ \ "friends").read[Seq[Long]](Reads.seq((__ \ "id").read[Long]))
)(Response.apply _)
结果将是:
r.reads(json)
scala> res2: play.api.libs.json.JsResult[Response] = JsSuccess(Response(1,List(1, 2, 3)),)
我正在使用 implicit val reads
来映射 Json,例如:
{
"id": 1
"friends": [
{
"id": 1,
"since": ...
},
{
"id": 2,
"since": ...
},
{
"id": 3,
"since": ...
}
]
}
一个案例class
case class Response(id: Long, friend_ids: Seq[Long])
我只能让它与反映 JSON friends
结构的中间 class 一起工作。但我从不在我的应用程序中使用它。有没有一种方法可以编写一个 Reads[Response]
对象,以便我的响应 class 可以直接映射到给定的 JSON?
您可以尝试以下方法
@annotation.tailrec
def go(json: Seq[JsValue], parsed: Seq[Long]): JsResult[Seq[Long]] =
json.headOption match {
case Some(o @ JsObject(_)) => (o \ "id").validate[Long] match {
case JsError(cause) => JsError(cause)
case JsSuccess(id) => go(json.tail, parsed :+ id)
}
case Some(js) => JsError(s"invalid friend JSON (expected JsObject): $js")
case _ => JsSuccess(parsed) // nothing more to read (success)
}
implicit val friendIdReader = Reads[Seq[Long]] {
case JsArray(values) => go(values, Nil)
case json => JsError(s"unexpected JSON: $json")
}
implicit val responseReader = Json.reads[Response]
// responseReader will use friendIdReader as Reads[Seq[Long]],
// for the property friend_ids
简单的方法可能是:
import play.api.libs.functional.syntax._
import play.api.libs.json.{JsValue, Json, _}
case class Response(id: Long, friend_ids: Seq[Friends])
object Response {
implicit val userReads: Reads[Response] = (
(JsPath \ "id").read[Long] and
(JsPath \ "friends").read[Seq[Friends]]
) (Response.apply _)
}
case class Friends(id: Long, since: String)
object Friends {
implicit val fmt = Json.format[Friends]
}
没有 case class Friends
我发现很难找到解决方案,但 post 如果我能找到
Edit: Added link for answer on Scala reedit
所以,我想进一步了解如何将 json 解析为模型,并决定在 Reedit 上提问。收到了一些很酷的链接,看看:
https://www.reddit.com/r/scala/comments/4bz89a/how_to_correctly_parse_json_to_scala_case_class/
您只需要对 friend_ids
进行显式 Reads.seq()
的简单读取[响应],例如
val r: Reads[Response] = (
(__ \ "id").read[Long] and
(__ \ "friends").read[Seq[Long]](Reads.seq((__ \ "id").read[Long]))
)(Response.apply _)
结果将是:
r.reads(json)
scala> res2: play.api.libs.json.JsResult[Response] = JsSuccess(Response(1,List(1, 2, 3)),)