Play Framework:地图没有隐式格式
Play Framework: No implicit format for Map
使用 Play 2.5 我似乎无法序列化 Map[SomeCaseClass, String]
case class SomeCaseClass(value: String)
implicit val formatSomeCaseClass = Json.format[SomeCaseClass]
Json.toJson(Map[SomeCaseClass, String](SomeCaseClass("") -> ""))
错误
No Json serializer found for type
scala.collection.immutable.Map[SomeCaseClass,String]. Try to implement
an implicit Writes or Format for this type.
除非我遗漏了一些明显的东西,否则上面的那个类型有一个隐式格式。
如果我尝试更简单的方法,例如:
Json.toJson(Something(""))
Json.toJson(Map[String, String]("" -> ""))
它工作正常。使用具有更复杂类型的 Map
时我错过了什么,例如SomeCaseClass
?
我认为这里的问题来自json。地图被转换为 JSON 个由 key/value 对组成的对象。这些对象中的键 must
是字符串。
因此 Map[String, T]
可以转换为 json 对象,但不能转换为任意对象 Map[U, T]
。
@Jack Bourne 是正确的。映射在播放中被视为 JsObject json,因此键必须可序列化为字符串值。
这是您可以用来定义地图格式的示例代码
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)
}
}
使用 Play 2.5 我似乎无法序列化 Map[SomeCaseClass, String]
case class SomeCaseClass(value: String)
implicit val formatSomeCaseClass = Json.format[SomeCaseClass]
Json.toJson(Map[SomeCaseClass, String](SomeCaseClass("") -> ""))
错误
No Json serializer found for type scala.collection.immutable.Map[SomeCaseClass,String]. Try to implement an implicit Writes or Format for this type.
除非我遗漏了一些明显的东西,否则上面的那个类型有一个隐式格式。
如果我尝试更简单的方法,例如:
Json.toJson(Something(""))
Json.toJson(Map[String, String]("" -> ""))
它工作正常。使用具有更复杂类型的 Map
时我错过了什么,例如SomeCaseClass
?
我认为这里的问题来自json。地图被转换为 JSON 个由 key/value 对组成的对象。这些对象中的键 must
是字符串。
因此 Map[String, T]
可以转换为 json 对象,但不能转换为任意对象 Map[U, T]
。
@Jack Bourne 是正确的。映射在播放中被视为 JsObject json,因此键必须可序列化为字符串值。
这是您可以用来定义地图格式的示例代码
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)
}
}