【问题标题】:How to remove List() and escape characters from response JSON in Scala如何从 Scala 中的响应 JSON 中删除 List() 和转义字符
【发布时间】:2016-01-21 01:18:26
【问题描述】:

我有以下函数,它接收 JSON 输入并使用 "com.eclipsesource" %% "play-json-schema-validator" % "0.6.2" 库根据 JSON 模式对其进行验证。当我收到无效的 JSON 时,一切正常,我尝试将所有违规行为收集到 List 中,然后将该列表与响应 JSON 一起返回。但是,我的 List 是用 List() 编码的,并且还有转义字符。我想让响应 JSON 看起来像这样:

{
  "transactionID": "123",
  "status": "error",
  "description": "Invalid Request Received",
  "violations": ["Wrong type. Expected integer, was string.", "Property action missing"]
}

而不是这个:(这是我现在得到的)

{
  "transactionID": "\"123\"",
  "status": "error",
  "description": "Invalid Request Received",
  "violations": "List(\"Wrong type. Expected integer, was string.\", \"Property action missing\")"
}

这是 JSON 验证的实际功能

def validateRequest(json: JsValue): Result = {

    {
      val logger = LoggerFactory.getLogger("superman")
      val jsonSchema = Source.fromFile(play.api.Play.getFile("conf/schema.json")).getLines.mkString
      val transactionID = (json \ "transactionID").get
      val result: VA[JsValue] = SchemaValidator.validate(Json.fromJson[SchemaType](
        Json.parse(jsonSchema.stripMargin)).get, json)

      result.fold(
        invalid = { errors =>

          var violatesList = List[String]()
          var invalidError = Map("transactionID" -> transactionID.toString(), "status" -> "error", "description" -> "Invalid Request Received")
          for (msg <- (errors.toJson \\ "msgs"))
            violatesList = (msg(0).get).toString() :: violatesList
          invalidError += ("violations" -> (violatesList.toString()))
          //TODO: Make this parsable JSON list
          val errorResponse = Json.toJson(invalidError)
          logger.error("""Message="Invalid Request Received" for transactionID=""" + transactionID.toString() + "errorResponse:" + errorResponse)
          BadRequest(errorResponse)

        },

        valid = {
          post =>
            db.writeDocument(json)
            val successResponse = Json.obj("transactionID" -> transactionID.toString, "status" -> "OK", "message" -> ("Valid Request Received"))
            logger.info("""Message="Valid Request Received" for transactionID=""" + transactionID.toString() + "jsonResponse:" + successResponse)
            Ok(successResponse)
        }
      )
    }

  }

更新 1

我在使用 Json.obj() 后得到了这个

{
  "transactionID": "\"123\"",
  "status": "error",
  "description": "Invalid Request Received",
  "violations": [
    "\"Wrong type. Expected integer, was string.\"",
    "\"Property action missing\""
  ]
}

【问题讨论】:

    标签: json scala playframework


    【解决方案1】:

    我通过修改这一行删除了转义字符:

    violatesList = (msg(0).get).toString() :: violatesList

    到:

    violatesList = (msg(0).get).as[String] :: violatesList

    【讨论】:

    • 在下面的答案中查看我的评论,了解其工作原理。此外,作为最佳实践,尝试使用 .asOpt[T] 而不是 .as[T] 来优雅地处理输入 JSON 与您预期不符的情况。选项是你的朋友。 :)
    • @emote_control:感谢您的解释。但是,当我将 .as[T] 更改为 .asOpt[T] 时,如 (msg(0).get).asOpt[String] :: violatesList 我收到此错误:Expression of List[Serializable] does not conform to expected type List[String]
    • 嗯,是的。您将获得Option[String] 而不是String,因此您无法将其添加到List[String]。你需要处理它。优点是,如果您的消息之一为空或不是字符串,则在运行时不会出现错误。缺点是您需要采取一个额外的步骤才能将列表展平为仅存在的字符串。最快的方法是声明var violatesList: List[Option[String]](),然后当你将它添加到 JSON 对象时,使用 `Json.obj("violations" -> AdvertisementsList.flatten)。
    • 尽管使用Json.obj 你可能不得不声明val violations = violatesList.flattenJson.obj("violations" -&gt; violations) 只是为了让编译器满意。 ETA:...因为 Json.obj 使用的隐式转换。
    【解决方案2】:

    您想要的是一个 JSON 数组,但通过在列表中调用 .toString(),您实际上是在传递一个字符串。 Play 有一个将 Lists 转换为 JSON 数组的隐式序列化程序,因此您实际上只需要做的比已经做的少 - 您可以从 violatesList.toString() 中删除 toString() 部分。

    此外,不要为您的 JSON 创建映射然后将其转换为 JSON,您可以使用 Json.obj,语法非常相似:

    val invalidError = Json.obj("transactionID" -> transactionID, "status" -> "error", "description" -> "Invalid Request Received")
    for (msg <- (errors.toJson \\ "msgs"))
      violatesList = (msg(0).get) :: violatesList
    val errorResponse = invalidError ++ Json.obj("violations" -> violatesList)
    

    关于你的转义引号,我想这是因为transactionIDmsgsJsStrings,所以当你用toString() 转换它们时,引号包括在内。只需在各处删除toString 就可以了。

    【讨论】:

    • 我删除了.toString(),现在我收到以下错误:[error] found : List[String] required: String [error] invalidError += ("violations" -&gt; violatesList) [error] ^
    • 如果您能正确阅读该错误,请告诉我,否则,我可以对实际问题进行编辑,以便正确格式化错误代码。
    • 谢谢!那行得通,但是转义字符仍然存在。请参阅我的更新 1。我如何也删除它们?
    • 其实transactionID和msgs就是JsLookupResults,所以可以调用.get。从 Play 2.4 开始,\ 运算符返回 JsLookupResult 而不是 JsValue。但是调用transactionId.get 会返回一个JsValue,而不是一个JsString,因为JsLookupResult 的内容可以是任何JsValue,并且你没有指定你期待一个JsString。所以你最终得到一个等于“123”的 JsValue,当你调用 .toString 时,它会从字面上解释“123”,并转义“字符。如果你知道你有一个字符串,请使用 transactionID.as[String ] 而不是 .get.
    • 或者更好的是,transactionID.asOpt[String],如果由于某种原因未定义 transactionID,它不会抛出异常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 2015-11-05
    • 1970-01-01
    • 2012-07-31
    • 2013-04-17
    相关资源
    最近更新 更多