Scala Play Json 地图格式 [Locale, String]
Scala Play Json Format for Map[Locale, String]
我有
类型的对象
Map[java.util.Locale, String]
我该如何进行 Json 写入/读取?我看过 couple other ,但我自己想不出解决办法。我得到了(但尚未测试)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]] = ???
?
这应该有效:
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 已经知道如何将 Locale
转换为 json,因为您提供了 Writes
,因此只需调用 toJson
即可。
对于 Reads
它有点复杂,你必须做一个映射,.value
returns a Map[String, JsValue]
其中第一个代表 Locale
对象,第二个是一个简单的字符串,所以调用 as[String]
已经可以给你你想要的东西了。
请注意,我已将所有内容包装在 JsSuccess
中,但您可能会认为您获得的 json 无法转换为 JsObject
,请应用 try/catch,并决定你想 return 成功还是失败。
如果 K
序列化为 JsString
,这里有一个函数将为您创建 Format[K,V]
:
/** 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) }
}
}
我有
类型的对象Map[java.util.Locale, String]
我该如何进行 Json 写入/读取?我看过 couple other
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]] = ???
?
这应该有效:
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 已经知道如何将 Locale
转换为 json,因为您提供了 Writes
,因此只需调用 toJson
即可。
对于 Reads
它有点复杂,你必须做一个映射,.value
returns a Map[String, JsValue]
其中第一个代表 Locale
对象,第二个是一个简单的字符串,所以调用 as[String]
已经可以给你你想要的东西了。
请注意,我已将所有内容包装在 JsSuccess
中,但您可能会认为您获得的 json 无法转换为 JsObject
,请应用 try/catch,并决定你想 return 成功还是失败。
如果 K
序列化为 JsString
,这里有一个函数将为您创建 Format[K,V]
:
/** 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) }
}
}