3

鉴于以下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)

最后一条语句无法编译,因为编译器没有找到 type 的 Json 序列化程序scala.collection.immutable.Map[MyEnum.Value,String]

问题:由于 Play 确实为 type 提供了序列化程序scala.collection.immutable.Map[String,String],而我的枚举实际上包含字符串,有没有办法重用默认的 JSON 序列化程序?

4

2 回答 2

6

内置Reads对象没有ReadsMap键中的参数定义 a。您可以执行以下操作:

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.

于 2014-09-18T05:14:41.503 回答
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 枚举替换。

于 2014-09-17T19:55:04.427 回答