【问题标题】:Parsing "stringified" JSON in scala/play在 scala/play 中解析“字符串化”JSON
【发布时间】:2025-12-29 14:05:06
【问题描述】:

我正在实现一个 Scala/Play API (apiA),它使用一个我无法控制的 API (apiB)。 ApiB 返回一个 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])

现在,scoresdata 被解析成什么类型​​并不重要,只要它不是包含 JSON 的字符串。

现在,如果 JSON 响应格式正确,则写入格式/读取/写入将很简单,但我有点想知道如何在解析为最终类型之前将内容转换为 JSON。

任何帮助将不胜感激。

【问题讨论】:

    标签: json scala playframework


    【解决方案1】:
    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)),)
    

    【讨论】: