Json 具有递归 class 定义的隐式格式
Json implicit format with recursive class definition
我定义了一个递归 class :
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]
我试图定义一个惰性 reads/write/format 包装器,但没有成功...
有人知道一个干净的方法吗?
如您所见,您不能在此处使用 JSON inception 宏,但您可以编写自己的 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
.
上的类型参数
对于那些来这里寻找轻微变体的人,我们在格式 class 中覆盖 reads
和 writes
(例如 [=16= 上的 example given =] 文档),你可以声明一个对你需要的对象的惰性引用:
lazy val tweetFormat: Format[Tweet] = TweetFormat
implicit object UserFormat extends Format[User] {
//...
}
//...
implicit object TweetFormat extends Format[Tweet] {
//...
只是一个更新。这已经固定了很长时间。例如,在 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。
我定义了一个递归 class :
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]
我试图定义一个惰性 reads/write/format 包装器,但没有成功... 有人知道一个干净的方法吗?
如您所见,您不能在此处使用 JSON inception 宏,但您可以编写自己的 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
.
对于那些来这里寻找轻微变体的人,我们在格式 class 中覆盖 reads
和 writes
(例如 [=16= 上的 example given =] 文档),你可以声明一个对你需要的对象的惰性引用:
lazy val tweetFormat: Format[Tweet] = TweetFormat
implicit object UserFormat extends Format[User] {
//...
}
//...
implicit object TweetFormat extends Format[Tweet] {
//...
只是一个更新。这已经固定了很长时间。例如,在 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。