首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >How to write a play-json Reads for Map[(Int,Int),A]?

How to write a play-json Reads for Map[(Int,Int),A]?
EN

Stack Overflow用户
提问于 2020-06-22 02:32:25
回答 1查看 35关注 0票数 0

我想反序列化这个json,它表示一个5x5的游戏场,并在(1,2)位置包含一个瓦片:

代码语言:javascript
复制
{
  "rows" : 5,
  "cols" : 5,
  "tiles" : [ {
    "row" : 1,
    "col" : 2,
    "tile" : {
      "number" : 3
    }
  } ]
}

所以我的case类是:

代码语言:javascript
复制
case class Tile(number: Int)
case class Rack(rows: Int, cols: Int, tiles: Map[(Int, Int), Tile])

我试着为班级机架写了一个Reads:

代码语言:javascript
复制
implicit val tileWrites = Json.writes[Tile]
implicit val tileReads = Json.reads[Tile]

implicit val reads: Reads[Rack] = (
    (__ \ "rows").read[Int] and
      (__ \ "cols").read[Int] and
      (__ \ "tiles").read[Map[(Int, Int), Tile]]
  ) (Rack.apply _)

但是我得到了这个错误:

代码语言:javascript
复制
Error:(50, 26) No Json deserializer found for type Map[(Int, Int),de.htwg.se.rummi.model.model.Tile]. Try to implement an implicit Reads or Format for this type.
      (__ \ "tiles").read[Map[(Int, Int), Tile]]

有人能解释一下我是如何为Map(Int,Int),Tile写一个Reads的吗

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-22 08:04:54

我不建议为Map这样的常见类型定义自定义Reads实例。相反,我建议为tiles定义一个自定义类型,并为此实现一个Reads。这样做的好处是,您可以将Reads实例放在伴生对象中,编译器将始终找到正确的实例,而您不必导入任何内容。

代码语言:javascript
复制
case class Tiles(tiles: Map[(Int, Int), Tile])

现在您可以在伴生对象中为Tiles定义一个Reads实例:

代码语言:javascript
复制
import play.api.libs.json._
import play.api.libs.functional.syntax._

object Tiles {
  implicit val reads: Reads[Tiles] =
    Reads.list {
      (
        (__ \ "row").read[Int] and
        (__ \ "col").read[Int] and
        (__ \ "tile").read[Tile]
      ) { (row, col, tile) => ((row, col), tile) }
    }.map(tuples => Tiles(tuples.toMap))
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62502859

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档