鉴于以下Enumeration
...
object MyEnum extends Enumeration {
type MyEnum = Value
val Val1 = Value("val1")
val Val2 = Value("val2")
val Val3 = Value("val3")
}
import MyEnum._
...以及以下Map
...
val m = Map(
val1 -> "one",
val2 -> "two",
val3 -> "three"
)
...我需要将m
转换为JSON:
import play.api.libs.json._
val js = Json.toJson(m)
最后一个语句无法编译,因为编译器找不到类型scala.collection.immutable.Map[MyEnum.Value,String]
的Json序列化程序。
问题:由于Play确实为类型scala.collection.immutable.Map[String,String]
提供了序列化程序,而我的枚举实际上包含字符串,有没有办法重用默认的JSON序列化程序?
答案 0 :(得分:5)
The built-in Reads
objects不要为密钥中的Reads
参数设置Map
。你可以这样做:
implicit def looserMapWrites[A <: AnyRef, B : Writes]: Writes[Map[A, B]] = Writes { o =>
Json.toJson(o.map { case (key, value) =>
key.toString -> value
})(Writes.mapWrites)
}
根据您的价值观,您会得到:
scala> Json.toJson(m)(looserMapWrites)
res1: play.api.libs.json.JsValue = {"val1":"one","val2":"two","val3":"three"}
如果您愿意,可以加强A
上的限制,使其不适用于任何AnyRef
。
答案 1 :(得分:1)
您需要为MyEnum.Value定义一个play.api.libs.json.Format,它将您的枚举转换为字符串表示形式。如下:
import play.api.libs.json._
object MyEnum extends Enumeration {
type MyEnum = Value
val Val1 = Value("val1")
val Val2 = Value("val2")
val Val3 = Value("val3")
implicit val myEnumWrites = new Writes[Value]{
def writes(o:Value)=JsString(o.toString)
}
}
MyEnum的更完整格式(读取和写入)可能看起来像
implicit val myEnumFormat = new Format[Value]{
def writes(o:Value)=JsString(o.toString)
def reads(json:JsValue):JsResult[Value]=json match {
case JsString("val1") =>JsSuccess(Val1)
case JsString("val2") =>JsSuccess(Val2)
case JsString("val3") =>JsSuccess(Val3)
case other => JsError(s"$other is not a valid value for MyEnum")
}
}
不建议使用枚举。它通常可以由密封特征和案例对象/案例类的层次结构或使用java枚举替换。