4

我有类型的对象

Map[java.util.Locale, String] 

我怎样才能为此进行 Json 写入/读取?我查看了其他几个 问题,但自己无法提出解决方案。我得到了(但还没有测试过)Locale 的东西

implicit val localeReads: Reads[Locale] = new Reads[Locale] {
  def reads(json: JsValue): JsResult[Locale] =
    json match {
      case JsString(langString) => JsSuccess(new Locale(langString))
      case _ => JsError("Locale Language String Expected")
    }
}

implicit val localeWrites: Writes[Locale] = new Writes[Locale] {
  def writes(locale: Locale) = JsString(locale.toString)
}

然后我该如何使用它

implicit val myMapReads: Reads[Map[Locale, String]] = ???
implicit val myMapWrites: Writes[Map[Locale, String]] = ???

?

4

2 回答 2

2

这应该有效:

implicit val localeReads: Reads[Locale] = new Reads[Locale] {
  def reads(json: JsValue): JsResult[Locale] =
    json match {
      case JsString(langString) => JsSuccess(new Locale(langString))
      case _ => JsError("Locale Language String Expected")
    }
}

implicit val localeWrites: Writes[Locale] = new Writes[Locale] {
  def writes(locale: Locale) = JsString(locale.toString)
}

implicit val myMapWrites: Writes[Map[Locale, String]] = new Writes[Map[Locale, String]] {
  override def writes(o: Map[Locale, String]): JsValue = Json.toJson(o)
}

implicit val myMapRead: Reads[Map[Locale, String]] = new Reads[Map[Locale, String]] {
  override def reads(json: JsValue): JsResult[Map[Locale, String]] = JsSuccess {
    json.as[JsObject].value.map {
      case (k, v) => (new Locale(k), v.as[String])
    }.toMap
  }
}

基本上 play 已经知道如何将 a 转换Locale为 json 因为Writes你提供了所以简单的调用toJson就可以了。

因为Reads它有点复杂,你必须做一个映射,.value返回一个Map[String, JsValue]第一个代表Locale对象的地方,第二个是一个简单的字符串,所以调用as[String]已经给你你想要的。

请注意,我已将所有内容都包装在 a 中,JsSuccess但您可能会假设您获得的 json 无法转换为JsObject,应用 try/catch 并决定您要返回成功还是失败。

于 2015-12-04T10:55:42.983 回答
0

这是一个函数,Format[K,V]如果K序列化为 a ,它将为您创建 a JsString

/** Play Json only supports Map[String,V]. This function creates a format for Map[K,V]. The type K should produce a JsString.
 * Otherwise the serialisation will fail. Which should be good enough since in valid json keys can only be strings. 
*/
def mapFormat[K, V](implicit fk: Format[K], fv: Format[V]): Format[Map[K, V]] = 
  new OFormat[Map[K, V]] {
    override def writes(o: Map[K, V]): JsObject = {
      val stringMap = o.map { case (k, v) => (Json.toJson[K](k).as[JsString].value, v) }
      Json.toJson(stringMap).as[JsObject]
    }

    override def reads(json: JsValue): JsResult[Map[K, V]] = {
      for {
        stringMap <- Json.fromJson[Map[String, V]](json)
        _         <- Json.fromJson[Set[K]](Json.toJson(stringMap.keySet))
      } yield stringMap.map { case (k, v) => (Json.fromJson[K](JsString(k)).get, v) }
    }
  }
于 2017-08-24T16:29:34.860 回答