我对 Scala 和那个不错的游戏框架的了解越来越多。但是有些事情困扰着我,我无法开始工作。
例如,我喜欢将泛型用于某种集合。但我需要将它们以 JSON 格式存储在我们的数据库中。有一个很酷的自动转换功能,但它不适用于泛型,我从未尝试过:-/
好吧,具体来说,先写代码:
case class InventorySlot(id: Long, item: Option[Item])
object InventorySlot {
implicit val fmt = Json.format[InventorySlot]
}
case class Inventory[T <: Item](slots: Vector[InventorySlot]) {
def length = slots.length
def items: Vector[T] = slots.map(slot => slot.item).flatten.asInstanceOf[Vector[T]]
def item(id: Long): Option[T] = {
slots.find(_.id == id) match {
case Some(slot: InventorySlot) =>
Some(slot.item.asInstanceOf[T])
case None =>
Logger.warn(s"slot with id $id not found")
None
}
}
}
object Inventory {
implicit val fmt = Json.format[Inventory]
}
Item 是可以放入该库存的不同项目的基本抽象类。没关系。但有时我想要一个仅适用于 ItemType A 的库存,我们称它为 AItem
。
所以我想用这样的东西创建我的库存:
val myInventory = Inventory[AItem]("content of vector here")
当我调用 myInventory.item(2)
时,我想获取插槽 2 中的项目, 它应该是 AItem
类型的对象,而不仅仅是 Item
。 (这就是我在这里使用泛型的原因)
所以问题
Inventory
的隐式格式显然不起作用。
Item
可以,还有所有特殊元素,我可以在下面发布它的代码,InventorySlot
应该也可以。
编译时的错误是:
Error:(34, 34) Play 2 Compiler:
C:\depot\mars\mainline\server\app\models\Test.scala:34: class Inventory takes type parameters
implicit val fmt = Json.format[Inventory]
^
我试着显式地写读写,比如
implicit val fmt = (
(__ \ "slots").format[Vector[InventorySlot]]
)(Inventory.apply, unlift(Inventory.unapply))
wich 甚至不能在我的 IDE 中工作,而且我找不到问题所在。 我很迷惑。我不知道我的错误在哪里,或者我做错了什么,或者我只是错过了什么。
我们将不胜感激。
我很无奈,我什至考虑过为所有可能的库存类型做一个类,比如
case class AItemInventory(protected var slots: Vector[InventorySlot]) extends Inventory[AItem](slots)
object AItemInventory {
implicit val fmt = Json.format[AItemInventory]
}
至于有效。没问题,一切都很好。所以……我不明白。如果它看起来完全一样,只是硬编码,为什么它会起作用?
附录
项目格式化程序,工作正常:
implicit val itemFormat = new Format[Item] {
override def reads(json: JsValue): JsResult[Item] = {
(json \ "itemType").as[ItemType] match {
case ItemType.AITEM => fmtAItem.reads(json)
}
}
override def writes(item: Item): JsValue = item match {
case subItem: AItem => fmtAItem.writes(subItem)
case _ => JsNumber(item.itemType.id)
}
}
最佳答案
object Inventory {
implicit def fmt[T <: Item](implicit fmt: Format[T]): Format[Inventory[T]] = new Format[Inventory[T]] {
def reads(json: JsValue): Inventory[T] = new Inventory[T] (
(json \ "blah").as[String]
)
def writes(i: Inventory[T]) = JsObject(Seq(
"blah" -> JsString(i.blah)
))
}
}
来源:documentation解释了如何为读取和写入执行此操作,而我在这里所做的是将这两者结合起来用于格式。
关于json - Scala Play - 如何格式化泛型以进行 JSON 转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31135563/