我正在使用Scala Play编写web服务。功能是好的,但我正在重构一些部分,使我的代码更易于阅读和干净。
我对每个实体类都使用隐式,使它们可转换为Json。我还注入了toJson
函数到Seq[MyEntityClass]
,以便能够通过调用单个函数来创建Json数组。
它看起来像这样:
case class MyModel(id: Option[Int], foo: String, bar: String)
object MyModel {
implicit val writer = Json.writes[MyModel]
implicit val reader: Reads[MyModel] = new Reads[MyModel] {
def reads(json: JsValue): JsResult[MyModel] = {
for {
foo <- (json "foo").validate[String]
bar <- (json "bar").validate[String]
} yield MyModel(None, foo, bar)
}
}
implicit def richMyModelSeq(apps: Seq[MyModel]) = new {
def toJson:JsValue = Json.toJson(apps)
}
// ...
}
我如何在一个超类中定义这个代码,而不是为每个实体类重复这个代码?
为什么不工作?
abstract class Jsonable {
implicit val writer = Json.writes[Jsonable]
implicit def richMyModelSeq(apps: Seq[MyModel]) = new {
def toJson:JsValue = Json.toJson(apps)
}
}
case class MyModel(id: Option[Int], foo: String, bar: String)
object MyModel extends Jsonable{
implicit val reader: Reads[MyModel] = new Reads[MyModel] {
def reads(json: JsValue): JsResult[MyModel] = {
for {
foo <- (json "foo").validate[String]
bar <- (json "bar").validate[String]
} yield MyModel(None, foo, bar)
}
}
// ...
}
你可以用这样的行:类可以扩展这个trait,伙伴对象可以扩展MyModelComp。
import play.api.libs.json._
trait MyModel {
def id: Option[Int]
def foo: String
def bar: String
}
trait MyModelComp[M <: MyModel] {
def cons: MyModel => M
implicit val writer = Json.writes[MyModel]
implicit def reader[M]: Reads[M] = new Reads[M] {
def reads(json: JsValue): JsResult[M] = {
for {
foo <- (json "foo").validate[String]
bar <- (json "bar").validate[String]
} yield cons(new MyModel {
override def foo: String = ???
override def bar: String = ???
override def id: Option[Int] = ???
})
}
}
}