播放如何为包含枚举的案例 class 实施隐式写入或格式
Play how to implement an implicit Writes or Format for a case class including an Enumeration
下面的 展示了如何使用 case class.
将枚举绑定到表单
但是在 Play 2.7.3 中,这段代码失败了:
No Json serializer found for type jura.SearchRequest. Try to implement an implicit Writes or Format for this type.
当我实现格式化程序时:
object SearchRequest {
implicit val searchRequestFormat: OFormat[SearchRequest] = Json.format[SearchRequest]
}
我明白了
No instance of play.api.libs.json.Format is available for
scala.Enumeration.Value in the implicit scope
我应该尝试为系统 scala.Enumeration 类型编写格式化程序吗?
或者当涉及枚举时,是否有另一种方法来实现格式化程序?
测试用例here.
要像cchantep说的那样将枚举写成字符串可以使用Writes.enumNameWrites,我们专门用来读写ID。因此我们在全局包中有一个 EnumFormat 用于枚举:
package object enums {
implicit def reads[E <: Enumeration](enum: E): Reads[E#Value] = new Reads[E#Value] {
def reads(json: JsValue): JsResult[E#Value] = json match {
case JsNumber(s) =>
try {
JsSuccess(enum.apply(s.toInt))
} catch {
case _: NoSuchElementException => JsError(s"Enumeration expected of type: '${enum.getClass}', but it does not appear to contain the value: '$s'")
}
case _ => JsError("Number value expected")
}
}
implicit def writes[E <: Enumeration]: Writes[E#Value] = new Writes[E#Value] {
def writes(v: E#Value): JsValue = JsNumber(v.id)
}
implicit def formatID[E <: Enumeration](enum: E): Format[E#Value] =
Format(reads(enum), writes)
def readsString[E <: Enumeration](enum: E): Reads[E#Value] = new Reads[E#Value] {
def reads(json: JsValue): JsResult[E#Value] = json match {
case JsString(s) => {
try {
JsSuccess(enum.withName(s))
} catch {
case _: NoSuchElementException => JsError(s"Enumeration expected of type: '${enum.getClass}', but it does not appear to contain the value: '$s'")
}
}
case _ => JsError("String value expected")
}
}
implicit def writesString[E <: Enumeration]: Writes[E#Value] = new Writes[E#Value] {
def writes(v: E#Value): JsValue = JsString(v.toString)
}
implicit def formatString[E <: Enumeration](enum: E): Format[E#Value] =
Format(readsString(enum), writesString)
}
并使用:
object SearchRequest extends Enumeration(1) {
type SearchRequest = Value
val ONE /*1*/ , TWO /*2*/ , ETC /*n*/ = Value
implicit val searchRequestFormat: Format[SearchRequest] = formatID(SearchRequest)
}
将以下内容添加到您的枚举对象
implicit object MatchFilterTypeFormatter extends Formatter[MatchFilterType.Value] {
override val format = Some(("format.enum", Nil))
override def bind(key: String, data: Map[String, String]) = {
try {
Right(MatchFilterType.withName(data.get(key).head))
} catch {
case e:NoSuchElementException => Left(Seq(play.api.data.FormError(key, "Invalid MatchFilterType Enumeration")))
}
}
override def unbind(key: String, value: MatchFilterType.Value) = {
Map(key -> value.toString)
}
}
implicit val matchFilterTypeFormat = new Format[MatchFilterType.MatchFilterType] {
def reads(json: JsValue) = JsSuccess(MatchFilterType.withName(json.as[String]))
def writes(myEnum: MatchFilterType.MatchFilterType) = JsString(myEnum.toString)
}
然后题中给出的Formatter/Controller就可以了
一个有效的测试用例是 here。
我将此库用于任何枚举:enumeratum
使用 Dotty 将会有很棒的 Enumerations,但在那之前我想转向 enumeratum 是在 Scala 中处理枚举的最佳方式。另见 Dotty - Enumerations。
作为奖励,有一个 play-json
扩展,请参阅 Play JSON Extension。
有了这个,您的代码将如下所示:
import enumeratum.{ PlayJsonEnum, Enum, EnumEntry }
sealed trait SearchRequest extends EnumEntry
object SearchRequest extends Enum[SearchRequest] with PlayJsonEnum[SearchRequest] {
val values = findValues
case object SuperRequest extends SearchRequest
case object SimpleRequest extends SearchRequest
..
}
本质上,PlayJsonEnum[SearchRequest]
完成了所有工作。
下面的
但是在 Play 2.7.3 中,这段代码失败了:
No Json serializer found for type jura.SearchRequest. Try to implement an implicit Writes or Format for this type.
当我实现格式化程序时:
object SearchRequest {
implicit val searchRequestFormat: OFormat[SearchRequest] = Json.format[SearchRequest]
}
我明白了
No instance of play.api.libs.json.Format is available for scala.Enumeration.Value in the implicit scope
我应该尝试为系统 scala.Enumeration 类型编写格式化程序吗?
或者当涉及枚举时,是否有另一种方法来实现格式化程序?
测试用例here.
要像cchantep说的那样将枚举写成字符串可以使用Writes.enumNameWrites,我们专门用来读写ID。因此我们在全局包中有一个 EnumFormat 用于枚举:
package object enums {
implicit def reads[E <: Enumeration](enum: E): Reads[E#Value] = new Reads[E#Value] {
def reads(json: JsValue): JsResult[E#Value] = json match {
case JsNumber(s) =>
try {
JsSuccess(enum.apply(s.toInt))
} catch {
case _: NoSuchElementException => JsError(s"Enumeration expected of type: '${enum.getClass}', but it does not appear to contain the value: '$s'")
}
case _ => JsError("Number value expected")
}
}
implicit def writes[E <: Enumeration]: Writes[E#Value] = new Writes[E#Value] {
def writes(v: E#Value): JsValue = JsNumber(v.id)
}
implicit def formatID[E <: Enumeration](enum: E): Format[E#Value] =
Format(reads(enum), writes)
def readsString[E <: Enumeration](enum: E): Reads[E#Value] = new Reads[E#Value] {
def reads(json: JsValue): JsResult[E#Value] = json match {
case JsString(s) => {
try {
JsSuccess(enum.withName(s))
} catch {
case _: NoSuchElementException => JsError(s"Enumeration expected of type: '${enum.getClass}', but it does not appear to contain the value: '$s'")
}
}
case _ => JsError("String value expected")
}
}
implicit def writesString[E <: Enumeration]: Writes[E#Value] = new Writes[E#Value] {
def writes(v: E#Value): JsValue = JsString(v.toString)
}
implicit def formatString[E <: Enumeration](enum: E): Format[E#Value] =
Format(readsString(enum), writesString)
}
并使用:
object SearchRequest extends Enumeration(1) {
type SearchRequest = Value
val ONE /*1*/ , TWO /*2*/ , ETC /*n*/ = Value
implicit val searchRequestFormat: Format[SearchRequest] = formatID(SearchRequest)
}
将以下内容添加到您的枚举对象
implicit object MatchFilterTypeFormatter extends Formatter[MatchFilterType.Value] {
override val format = Some(("format.enum", Nil))
override def bind(key: String, data: Map[String, String]) = {
try {
Right(MatchFilterType.withName(data.get(key).head))
} catch {
case e:NoSuchElementException => Left(Seq(play.api.data.FormError(key, "Invalid MatchFilterType Enumeration")))
}
}
override def unbind(key: String, value: MatchFilterType.Value) = {
Map(key -> value.toString)
}
}
implicit val matchFilterTypeFormat = new Format[MatchFilterType.MatchFilterType] {
def reads(json: JsValue) = JsSuccess(MatchFilterType.withName(json.as[String]))
def writes(myEnum: MatchFilterType.MatchFilterType) = JsString(myEnum.toString)
}
然后题中给出的Formatter/Controller就可以了
一个有效的测试用例是 here。
我将此库用于任何枚举:enumeratum
使用 Dotty 将会有很棒的 Enumerations,但在那之前我想转向 enumeratum 是在 Scala 中处理枚举的最佳方式。另见 Dotty - Enumerations。
作为奖励,有一个 play-json
扩展,请参阅 Play JSON Extension。
有了这个,您的代码将如下所示:
import enumeratum.{ PlayJsonEnum, Enum, EnumEntry }
sealed trait SearchRequest extends EnumEntry
object SearchRequest extends Enum[SearchRequest] with PlayJsonEnum[SearchRequest] {
val values = findValues
case object SuperRequest extends SearchRequest
case object SimpleRequest extends SearchRequest
..
}
本质上,PlayJsonEnum[SearchRequest]
完成了所有工作。