在 scala/play 中解析 "stringified" JSON
Parsing "stringified" JSON in scala/play
我正在实施一个 Scala/Play API (apiA),它使用我无法控制的 API (apiB)。 ApiB returns 一个 JSON 响应,在某些情况下 JSON 嵌入到字符串中。示例:
{
"name":"some_name",
"scores": "[[10,15]]",
"data": "{\"attr1\":\"value1\",\"attr2\":\"value3\"}"
}
ApiA 需要在将所有数据传递给客户端之前访问 name
的值,并且应该将其正确地提供给客户端 JSON。
我正在考虑将原始响应解析为
case class Response(name: String, scores: JsValue, data: JsValue)
或
case class Response(name: String, scores: Seq[Seq[Int]], data: Map[String, String])
目前 scores
和 data
被解析成什么类型并不重要,只要它不是包含 JSON.
的字符串即可
现在,如果 JSON 响应格式正确,那么写 format/reads/writes 会很简单,但我有点想不通如何将内容转换为 JSON在解析为最终类型之前。
如有任何帮助,我们将不胜感激。
case class Response(name: String, scores: Seq[Seq[Int]], data: Map[String, String])
import play.api.libs.json._
val stringified = Reads[JsValue] {
_.validate[String].flatMap { raw =>
try {
JsSuccess(Json.parse(raw))
} catch {
case cause =>
JsError(cause.getMessage)
}
}
}
implicit val respReads = Reads[Response] { js =>
for {
name <- (js \ "name").validate[String]
scores <- (js \ "scores").validate(
stringified).flatMap(_.validate[Seq[Seq[Int]]])
data <- (js \ "data").validate(
stringified).flatMap(_.validate[Map[String, String]])
} yield Response(name, scores, data)
}
Json.parse("""{
"name":"some_name",
"scores": "[[10,15]]",
"data": "{\"attr1\":\"value1\",\"attr2\":\"value3\"}"
}""").validate[Response]
// JsSuccess(Response(some_name,Vector(Vector(10, 15)),Map(attr1 -> value1, attr2 -> value3)),)
我正在实施一个 Scala/Play API (apiA),它使用我无法控制的 API (apiB)。 ApiB returns 一个 JSON 响应,在某些情况下 JSON 嵌入到字符串中。示例:
{
"name":"some_name",
"scores": "[[10,15]]",
"data": "{\"attr1\":\"value1\",\"attr2\":\"value3\"}"
}
ApiA 需要在将所有数据传递给客户端之前访问 name
的值,并且应该将其正确地提供给客户端 JSON。
我正在考虑将原始响应解析为
case class Response(name: String, scores: JsValue, data: JsValue)
或
case class Response(name: String, scores: Seq[Seq[Int]], data: Map[String, String])
目前 scores
和 data
被解析成什么类型并不重要,只要它不是包含 JSON.
现在,如果 JSON 响应格式正确,那么写 format/reads/writes 会很简单,但我有点想不通如何将内容转换为 JSON在解析为最终类型之前。
如有任何帮助,我们将不胜感激。
case class Response(name: String, scores: Seq[Seq[Int]], data: Map[String, String])
import play.api.libs.json._
val stringified = Reads[JsValue] {
_.validate[String].flatMap { raw =>
try {
JsSuccess(Json.parse(raw))
} catch {
case cause =>
JsError(cause.getMessage)
}
}
}
implicit val respReads = Reads[Response] { js =>
for {
name <- (js \ "name").validate[String]
scores <- (js \ "scores").validate(
stringified).flatMap(_.validate[Seq[Seq[Int]]])
data <- (js \ "data").validate(
stringified).flatMap(_.validate[Map[String, String]])
} yield Response(name, scores, data)
}
Json.parse("""{
"name":"some_name",
"scores": "[[10,15]]",
"data": "{\"attr1\":\"value1\",\"attr2\":\"value3\"}"
}""").validate[Response]
// JsSuccess(Response(some_name,Vector(Vector(10, 15)),Map(attr1 -> value1, attr2 -> value3)),)