我正在尝试做出这样的想法:
case class Obj(name: String, list: List[Integer], isPossible: Boolean) {
override def apply(name: String, list: List[Integer]): Obj = {
Obj(name, list, list.exists((x: Integer) => x >= 10 && x <= 100))
}
}
implicit val objReads: Reads[Obj] = (
(__ \ "name").read[String] and
(__ \ "list").read[List[Integer]]
)(Book.apply _)
但它无法编译,它返回一个错误:
Overloaded method value [apply] cannot be applied to ((String, List[Integer], Boolean) => models.Api.Obj)
是否可以做到这一点,或者只是我必须在案例类和读取组合器中具有相同数量的字段,这是不可能的
最佳答案
这里有一些问题。首先,案例类的 apply
方法是在其伴生对象中定义的,而不是案例类本身。第二个问题是,一旦在伴生对象中定义了 apply
方法,就会在 Obj.apply _
中导致不明确的引用错误。这是因为您的 apply
声明是重载,而不是覆盖,因为签名不匹配。
解决此问题的一种方法是从 Obj
的构造函数中删除 isPossible
,并将其设为方法或 val。您仍然可以以相同的方式访问它。
case class Obj(name: String, list: List[Int]) {
val isPossible: Boolean = list.exists((x: Int) => x >= 10 && x <= 100)
}
object Obj {
implicit val objReads: Reads[Obj] = (
(__ \ "name").read[String] and
(__ \ "list").read[List[Int]]
)(Obj.apply _)
}
这带来的唯一问题是 isPossible
将不再包含在 JSON 写入中,可以像这样修复:
implicit val objWrites: Writes[Obj] = (
(__ \ "name").write[String] and
(__ \ "list").write[List[Int]] and
(__ \ "isPossible").write[Boolean]
)( obj => (obj.name, obj.list, obj.isPossible) )
或者,您可以将重载的 apply
重命名为其他名称,并将其用于 Reads
而不是 Obj.apply
。但是,我认为将 isPossible
保留为 val
更好,因为它的计算将在对象创建时完成,而不是在传递给构造函数时完成。这将确保您不能仅使用 isPossible
的无效状态来调用 Obj("test", List(1), true)
。
关于json - Play 框架,JSON 读取组合器,具有覆盖的 apply 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25710711/