有更好的方法吗?我想避免在Mammal伴侣对象的读写方法上进行模式匹配。
OTOH我怀疑无形的可扩展记录可以在这里提供帮助,但我不确定如何使用它。有谁能告诉我如何使用无形的方式来完成它?import play.api.libs.json._
object X {
trait Animal {
val category: String
val subcategory: String
}
sealed trait Mammal extends Animal {
override val category = Mammal.name
}
object Man {
implicit val format = Json.format[Man]
val name = "Man"
}
case class Man(weight: Int) extends Mammal {
override val subcategory = Man.name
}
object Whale {
implicit val format = Json.format[Whale]
val name = "Whale"
}
case class Whale(weight: Int) extends Mammal {
override val subcategory = Whale.name
}
object Mammal {
val name = "Mammal"
implicit val format: Format[Mammal] = new Format[Mammal] {
def writes(m: Mammal): JsValue = {
val json = m match {
case x: Man => Json.toJson(x)(Man.format)
case x: Whale => Json.toJson(x)(Whale.format)
}
json.as[JsObject] + ("category" -> JsString(m.category)) + ("subcategory" -> JsString(m.subcategory))
}
def reads(json: JsValue): JsResult[Mammal] = {
(json \ "subcategory").as[String] match {
case Man.name => json.validate[Man]
case Whale.name => json.validate[Whale]
case unknown => JsError(s"Unknown subcategory '$unknown'")
}
}
}
}
}
import X._
val man: Mammal = Man(100)
val whale: Mammal = Whale(1000)
val json = Json.toJson(man)
val read = json.validate[Mammal]
答案 0 :(得分:1)
为了写作,我创建了一个通用方法。
def writes(m: Mammal) = {
val mapTest = (Map[String, Any]() /: m.getClass.getDeclaredFields) {(a, f) =>
f.setAccessible(true)
a + (f.getName -> f.get(m))
} - "$outer"
Json.obj(mapTest.map{case (s, o) =>
val ret:(String, JsValueWrapper) = o match {
case _:String => s -> JsString(o.asInstanceOf[String])
case _:Int => s -> JsNumber(o.asInstanceOf[Int])
case _ => s -> JsString("")
}
ret
}.toSeq:_*)
}
json: play.api.libs.json.JsValue = {"weight":100,"subcategory":"Man","category":"Mammal"}