Rhy*_*ury 4 json scala playframework-2.0 play-json
上下文
我有一个案例类,它是层次结构中的一个项目,它引用自己是这样的:
case class Node(
name: String,
children: Option[Seq[Node]] = None
)
Run Code Online (Sandbox Code Playgroud)
我想要一个PlayJson Format
.
通常,您可以这样做:
implicit lazy val formatter = Json.format[MyCaseClass]
Run Code Online (Sandbox Code Playgroud)
但这不起作用.
为什么?
PlayJson使用Scala宏Format
为case类生成一个,它将遍历所有字段,当它到达字段时children
,它将查找Node
尚未构造的现有格式化程序,以编译错误结束:
No implicit format for Option[Seq[Node]] available.
[error] implicit lazy val formatter = Json.format[Node]
Run Code Online (Sandbox Code Playgroud)
问题
什么是最好的方法来解决这个问题?
这是PlayJson格式宏的已知问题吗?
这可以recursive types
在play-json docs中找到:
import play.api.libs.functional.syntax._
import play.api.libs.json.{Reads, Writes, _}
case class Node(name: String, children: Option[Seq[Node]] = None)
implicit lazy val nodeReads: Reads[Node] = (
(__ \ "name").read[String] and
(__ \ "children").lazyReadNullable(Reads.seq[Node](nodeReads))
)(Node)
implicit lazy val nodeWrites: Writes[Node] = (
(__ \ "name").write[String] and
(__ \ "children").lazyWriteNullable(Writes.seq[Node](nodeWrites))
)(unlift(Node.unapply))
Run Code Online (Sandbox Code Playgroud)
因为在这种情况下Reads
并且Writes
是对称的,所以您可以将整个事物创建为单个Format
:
implicit lazy val nodeFormat: Format[Node] = (
(__ \ "name").format[String] and
(__ \ "children").lazyFormatNullable(Reads.seq[Node](nodeFormat), Writes.seq[Node](nodeFormat))
)(Node.apply, unlift(Node.unapply))
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
251 次 |
最近记录: |