Play Framework Json 中的动态 Json 值
Dynamic Json values in Play Framework Json
我目前正在使用 Play 框架 json 解析器来解析我的 scala 代码中的 json 字符串。
我有以下 class:
case class Address(address: String,
gps: GPS,
country: String) {}
object Address {
implicit val reads: Reads[Address] = (
(JsPath \ "address").read[String] and
(JsPath \ "gps").read[GPS] and
(JsPath \ "country").read[String]
) (Address.apply _)
implicit val writes: Writes[Address] = (
(JsPath \ "address").write[String] and
(JsPath \ "gps").write[GPS] and
(JsPath \ "country").write[String]
) (unlift(Address.unapply))
}
适用于以下 json:
{
"address": "123 Fake Street",
"country": "USA",
"gps": { ... }
}
问题在于,在某些情况下,json 可能会将 gps 字段改为不解析的字符串,即
{
"address": "123 Fake Street",
"country": "USA",
"gps": "123abc"
}
现在我知道我不能让 gps 成员既是字符串又是 GPS 对象,但是有没有办法让它成为 Option[GPS] 并且只有在 json 包含一个 gps 对象?
您的 impl 只需更改很少的部分。
您需要将字段 "gps" 读取为类似于 JsValue 'safe' 的内容,然后尝试将其映射到您的 GPS 案例中 class 如果可以,如果不能,return None.
case class GPS(a:String, b:String)
object GPS {
val travelInfoReads = Json.reads[GPS]
val travelInfoWrites = Json.writes[GPS]
implicit val travelInfoFormat: Format[GPS] = Format(travelInfoReads, travelInfoWrites)
}
case class Address(address: String,
gps: Option[GPS],
country: String) {}
object Address {
implicit val reads: Reads[Address] = (
(JsPath \ "address").read[String] and
(JsPath \ "gps").read[JsValue].map(js => js.asOpt[GPS]) and
(JsPath \ "country").read[String]
) (Address.apply _)
implicit val writes: Writes[Address] = (
(JsPath \ "address").write[String] and
(JsPath \ "gps").writeNullable[GPS] and
(JsPath \ "country").write[String]
) (unlift(Address.unapply))
}
我也测试过:
val json = Json.toJson(Address("1",Some(GPS("a","b")),"2"))
println(json)
println(json.as[Address])
val newObj: JsObject = (json.as[JsObject] - "gps") + ("gps" -> JsNumber(1))
println(newObj)
val a = newObj.as[Address]
println(a)
a must beEqualTo(Address("1",None,"2"))
输出就像
{"address":"1","gps":{"a":"a","b":"b"},"country":"2"}
Address(1,Some(GPS(a,b)),2)
{"address":"1","country":"2","gps":1}
Address(1,None,2)
我目前正在使用 Play 框架 json 解析器来解析我的 scala 代码中的 json 字符串。
我有以下 class:
case class Address(address: String,
gps: GPS,
country: String) {}
object Address {
implicit val reads: Reads[Address] = (
(JsPath \ "address").read[String] and
(JsPath \ "gps").read[GPS] and
(JsPath \ "country").read[String]
) (Address.apply _)
implicit val writes: Writes[Address] = (
(JsPath \ "address").write[String] and
(JsPath \ "gps").write[GPS] and
(JsPath \ "country").write[String]
) (unlift(Address.unapply))
}
适用于以下 json:
{
"address": "123 Fake Street",
"country": "USA",
"gps": { ... }
}
问题在于,在某些情况下,json 可能会将 gps 字段改为不解析的字符串,即
{
"address": "123 Fake Street",
"country": "USA",
"gps": "123abc"
}
现在我知道我不能让 gps 成员既是字符串又是 GPS 对象,但是有没有办法让它成为 Option[GPS] 并且只有在 json 包含一个 gps 对象?
您的 impl 只需更改很少的部分。 您需要将字段 "gps" 读取为类似于 JsValue 'safe' 的内容,然后尝试将其映射到您的 GPS 案例中 class 如果可以,如果不能,return None.
case class GPS(a:String, b:String)
object GPS {
val travelInfoReads = Json.reads[GPS]
val travelInfoWrites = Json.writes[GPS]
implicit val travelInfoFormat: Format[GPS] = Format(travelInfoReads, travelInfoWrites)
}
case class Address(address: String,
gps: Option[GPS],
country: String) {}
object Address {
implicit val reads: Reads[Address] = (
(JsPath \ "address").read[String] and
(JsPath \ "gps").read[JsValue].map(js => js.asOpt[GPS]) and
(JsPath \ "country").read[String]
) (Address.apply _)
implicit val writes: Writes[Address] = (
(JsPath \ "address").write[String] and
(JsPath \ "gps").writeNullable[GPS] and
(JsPath \ "country").write[String]
) (unlift(Address.unapply))
}
我也测试过:
val json = Json.toJson(Address("1",Some(GPS("a","b")),"2"))
println(json)
println(json.as[Address])
val newObj: JsObject = (json.as[JsObject] - "gps") + ("gps" -> JsNumber(1))
println(newObj)
val a = newObj.as[Address]
println(a)
a must beEqualTo(Address("1",None,"2"))
输出就像
{"address":"1","gps":{"a":"a","b":"b"},"country":"2"}
Address(1,Some(GPS(a,b)),2)
{"address":"1","country":"2","gps":1}
Address(1,None,2)