带有递归类定义的Json隐式格式

时间:2015-06-08 14:40:37

标签: json scala recursion playframework play-json

我定义了一个递归类:

case class SettingsRepository(id: Option[BSONObjectID],
                          name: Option[String],
                          children: Option[List[SettingsRepository]])

使用JSON隐式格式,如下所示:

implicit val repositoryFormat = Json.format[SettingsRepository]

如何解决此编译错误? :

No implicit format for Option[List[models.practice.SettingsRepository]] available.
In /path/to/the/file.scala:95

95 implicit val repositoryFormat = Json.format[SettingsRepository] 

我试图定义一个懒惰的读/写/格式包装器而没有任何成功...... 有人知道干净的方法吗?

任何帮助将不胜感激;

提前谢谢。

3 个答案:

答案 0 :(得分:7)

正如您所发现的,您不能在此处使用JSON初始宏,但您可以编写自己的Format(请注意,我已将BSONObjectID替换为Long一个完整的工作例子):

import play.api.libs.functional.syntax._
import play.api.libs.json._

case class SettingsRepository(
  id: Option[Long],
  name: Option[String],
  children: Option[List[SettingsRepository]]
)

implicit val repositoryFormat: Format[SettingsRepository] = (
  (__ \ 'id).formatNullable[Long] and
  (__ \ 'name).formatNullable[String] and
  (__ \ 'children).lazyFormatNullable(implicitly[Format[List[SettingsRepository]]])
)(SettingsRepository.apply, unlift(SettingsRepository.unapply))

诀窍是提供显式类型注释并使用implicitly而不仅仅是lazyFormatNullable上的类型参数。

答案 1 :(得分:0)

For others who came here looking for a slight variant where we override reads and writes in the Format class (like the example given on the API docs), you can declare a lazy reference to your needed object:

  lazy val tweetFormat: Format[Tweet] = TweetFormat
  implicit object UserFormat extends Format[User] {
  //...
  }

  //...
  implicit object TweetFormat extends Format[Tweet] {
  //...

答案 2 :(得分:0)

只是更新。这已经修复了很长时间。例如,在 play-json 版本 2.3.9(Maven 上可用的最旧版本)中,以下内容有效:

import play.api.libs.json._

case class SettingsRepository(id: Option[Int],
                              name: Option[String],
                              children: Option[List[SettingsRepository]])

implicit val repositoryFormat = Json.format[SettingsRepository]

val s = SettingsRepository(Some(2), Some("name"), Some(List(SettingsRepository(Some(1), Some(""), None))))
println(Json.toJsObject(s))

和输出:

{"id":2,"name":"name","children":[{"id":1,"name":""}]}

代码在 Scastie 运行。