【问题标题】:scala-play 2.4.11, is it possible to desearialize Map with case class as key?scala-play 2.4.11,是否可以以案例类为键对 Map 进行反序列化?
【发布时间】:2018-05-24 21:24:49
【问题描述】:

我正在尝试处理 play-json,但效果并不好。 这是我的案例课程

sealed case class Items(items: List[Item])

sealed case class Item(path: String, itemCounters: Map[ItemCategory, Long])

sealed case class ItemCategory(repository: Repository)

sealed case class Repository(env: String)

这里我正在尝试解析 json:

implicit lazy val repositoryFormat = Json.format[Repository]
implicit lazy val itemCategoryFormat = Json.format[ItemCategory]
implicit lazy val itemFormat = Json.format[Item]
implicit lazy val itemsFormat = Json.format[Items]

Json.parse(str).as[Items]

我得到异常: 没有可用的 Map[ItemCategory,Long] 的隐式格式。

为什么?

【问题讨论】:

  • 能否请您也发布 JSON?
  • 编译时失败:(
  • 孤立地这段代码有效,我认为您的示例中缺少/不同的东西。

标签: scala playframework play-json


【解决方案1】:

失败是因为 play-json 对如何反序列化 Item 中的 itemCounters: Map[ItemCategory, Long] 属性感到困惑。

确实,如果键是String,则可以直接处理 JSON 映射。但是对于键中的其他结构化对象,它变得有点困难,比如问题中的ItemCategory。当然,带有这样key的JSON不能是{ "repository": { "env": "demo" } }: 1

所以,我们需要明确说明这种 Map 的反序列化。我假设 ItemCategory 的键是基础 ItemCategory.repository.env 值,但它可以是任何其他属性,具体取决于您的有效数据模型。

我们为这种地图提供了Reads 实现:

implicit lazy val itemCategoryMapReads = new Reads[Map[ItemCategory, Long]] {
  override def reads(jsVal: JsValue): JsResult[Map[ItemCategory, Long]] = {
    JsSuccess(
      // the original string -> number map is translated into ItemCategory -> Long
      jsVal.as[Map[String, Long]].map{
        case (category, id) => (ItemCategory(Repository(category)), id)
      }
    )
  }
}

以及各自的Format(带有Writes 的存根,我们现在不需要):

implicit lazy val itemCategoryMapFormat = Format(itemCategoryMapReads, (catMap: Map[ItemCategory, Long]) => ???)

基础 JSON 现已正确映射:

val strItemCat =
  """
    | {
    |   "rep1": 1,
    |   "rep2": 2,
    |   "rep3": 3
    | }
  """.stripMargin

println(Json.parse(strItemCat).as[Map[ItemCategory, Long]])
// Map(ItemCategory(Repository(rep1)) -> 1, ItemCategory(Repository(rep2)) -> 2, ItemCategory(Repository(rep3)) -> 3)

对于其他案例类,您已经定义的简单格式应该可以正常工作,前提是它们按从最具体到最不具体的顺序声明(从RepositoryItems)。

【讨论】:

  • 谢谢,将对象放入映射键是一个错误的决定。谢谢。我没想到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-14
  • 2010-12-17
  • 2013-08-12
  • 2013-08-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多