在JsPath.scala
中,lazyRead
方法的说明如下:
/*case class User(id: Long, name: String, friend: User)
implicit lazy val UserReads: Reads[User] = (
(__ \ 'id).read[Long] and
(__ \ 'name).read[String] and
(__ \ 'friend).lazyRead(UserReads)
)(User.apply _) */
def lazyRead[T](r: => Reads[T]): Reads[T] = Reads(js => Reads.at[T]
(this)(r).reads(js))
当我尝试执行上述示例的简化版本时:
case class User(id:Int, user: User)
val userJsVal = Json.parse(
"""
| {
| "id" : 22,
| "user" : { "id":2 }
| }
""".stripMargin)
implicit lazy val UserReads: Reads[User] = (
(__ \ 'id).read[Int] and
( __ \ 'user).lazyRead(UserReads)
)(User.apply _)
val us = Json.fromJson[User](userJsVal)(UserReads);
us match {
case s:JsSuccess[User] => println(s.get)
case e:JsError => println(JsError.toJson(e).toString()) }
我收到错误:
{"obj.user.user":[{"msg":["error.path.missing"],"args":[]}]}
我尝试将最里面的“user”设置为null,但这也不起作用。我应该如何构建我的json或添加终止条件:
( __ \ 'user).lazyRead(UserReads)
获得有效的反序列化输出?
答案 0 :(得分:0)
如@Andriy所述,您的User对象必须有一个Option [User],否则您的内部对象将始终需要无限制地拥有另一个用户。 您可以注意到,在您的JSON示例中,内部用户已经没有其他用户。 然后在将内部用户更改为可选后,您应该使用lazyReadNullable,这是您修复的示例:
import play.api.libs.json.{JsError, JsSuccess, Json, Reads}
import play.api.libs.json._
import play.api.libs.functional.syntax._
case class User(id:Int, user: Option[User])
val userJsVal = Json.parse(
"""
| {
| "id" : 22,
| "myuser" : { "id":2 }
| }
""".stripMargin)
implicit lazy val UserReads: Reads[User] = (
(__ \ 'id).read[Int] and
( __ \ 'myuser).lazyReadNullable(UserReads)
)(User.apply _)
val us = Json.fromJson[User](userJsVal)(UserReads)
us match {
case s:JsSuccess[User] => println(s.get)
case e:JsError => println(JsError.toJson(e).toString()) }
答案 1 :(得分:0)
如果你没有选择JSON解析器,那么试试jsoniter-scala
- 它内置支持递归结构和许多其他好东西,比如the best performance characteristics comparing to other JSON parsers for Scala。