【问题标题】:Play Framework: No implicit format for MapPlay Framework:地图没有隐式格式
【发布时间】:2019-10-20 17:48:36
【问题描述】:

使用 Play 2.5 我似乎无法序列化 Map[SomeCaseClass, String]

case class SomeCaseClass(value: String)

implicit val formatSomeCaseClass = Json.format[SomeCaseClass]

Json.toJson(Map[SomeCaseClass, String](SomeCaseClass("") -> ""))

错误

找不到类型的 Json 序列化程序 scala.collection.immutable.Map[SomeCaseClass,String]。尝试实施 此类型的隐式写入或格式。

除非我遗漏了一些明显的东西,否则上面有该类型的隐式格式。

如果我尝试更简单的方法,例如:

Json.toJson(Something(""))
Json.toJson(Map[String, String]("" -> ""))

它工作正常。使用具有更复杂类型的Map 时我缺少什么,例如SomeCaseClass?

【问题讨论】:

  • 它对我有用 - 请参阅 scalafiddle.io/sf/9tbdZpk/0
  • @pme 我想知道它是否是 scala/play 版本的东西,我使用的是 play 2.5
  • 它看起来像 - 当我没记错时,Scalafiddle 使用 2.6。无论如何,它生成的格式无论如何都不是你想要的;)。

标签: scala playframework playframework-2.5 play-json


【解决方案1】:

我认为这里的问题来自 json。映射被转换为由键/值对组成的 JSON 对象。这些对象must 中的键是字符串。

因此,Map[String, T] 可以转换为 json 对象,但不能转换为任意的 Map[U, T]

【讨论】:

  • 是的,我认为你是对的,我交换了密钥和值,它可以工作,谢谢
  • 鉴于我的案例类只是一个字符串的包装器,你能想出什么办法让它工作吗?
  • 最简单的方法可能是删除你的案例类
  • 我问的原因是我希望用 Enum 替换我的案例类,所以它只会序列化为字符串
  • 如果你只想写它,你可以在写对应的字符串之前映射你的枚举值:mapToWrite.map { case (key, value) => (key.toString, value) }
【解决方案2】:

@Jack Bourne 是正确的。 map 在 play json 中被视为 JsObject,因此键必须可序列化为字符串值。

这是一个示例代码,您可以使用它来定义地图格式

import play.api.libs.json._

case class SomeCaseClass(value: String)

implicit val formatSomeCaseClass = Json.format[SomeCaseClass]

Json.toJson(Map[SomeCaseClass, String](SomeCaseClass("") -> ""))

implicit val someCaseClassToStringFormat = new Format[Map[SomeCaseClass, String]] {
override def writes(o: Map[SomeCaseClass, String]): JsValue = {
  val tuples = o.toSeq.map {
    case (key, value) => key.value -> Json.toJsFieldJsValueWrapper(value)
  }
  Json.obj(tuples: _*)
}

override def reads(json: JsValue): JsResult[Map[SomeCaseClass, String]] = {
  val resultMap: Map[SomeCaseClass, String] = json.as[JsObject].value.toSeq.map {
    case (key, value) => Json.fromJson[SomeCaseClass](value) match {
      case JsSuccess(someCaseClass, _) => someCaseClass -> key
      case JsError(errors) => throw new Exception(s"Unable to parse json :: $value as SomeCaseClass because of ${JsError.apply(errors)}")
    }
  }(collection.breakOut)
  JsSuccess(resultMap)
 }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-13
    • 2013-02-04
    • 2017-04-11
    • 1970-01-01
    • 1970-01-01
    • 2017-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多