繁体   English   中英

在Scala播放中重构json

[英]Restructure a json in scala play

以下代码获取请求正文并验证并创建json:object ValidateDBConfigJson {

implicit val reads: Reads[ValidateDetails] = (
  (JsPath \ "name").read[String].filter(JsonValidationError("Invalid name"))(_.length > 0) and
    (JsPath \ "email").read[String].filter(JsonValidationError("Invalid email"))(_.length > 0) and
)(ValidateDetails.apply _)

}

def index() = Action { implicit request =>
val bodyAsJson = request.body.asJson.get
bodyAsJson.validate[ValidateDetails] match {
  case success: JsSuccess[ValidateDetails] => {
    Ok(Json.parse("succeeded!"))
  }
  case JsError(error) =>
    BadRequest(JsError.toJson(error))
}

}

json看起来像这样:

{
    "obj.name": [
        {
          "msg": [
          "error.expected.jsstring"
          ],
          "args": []
        }
    ],
    "obj.email": [
         {
            "msg": [
            "Invalid email"
            ],
            "args": []
         }
    ]
}

我想以以下格式进行结构化:

{
 "ErrorMessages" : 
    [
    "error.expected.jsstring", 
    "Invalid email"
    ]
 }

序言:当我使用Play解析JSON时,我更喜欢使用case类/对象而不是隐式读取,因此此答案将涵盖执行此操作的方法。 进行隐式读取可能有一种更简单的方法,但是我对隐式读取并不熟悉。

首先,为您要从JSON中获取的所有内容定义一个case class

object Input {
  case class Err(msg: Seq[String], args: Seq[String])

  object Err {
    implicit val format: OFormat[Err] = Json.format[Err]
  }

  case class ValidateDetails(`obj.name`: Seq[Err], `obj.email`: Seq[Err])

  object ValidateDetails {
    implicit val format: OFormat[ValidateDetails] = Json.format[ValidateDetails]
  }
}

注意:Play不知道如何处理用户定义的案例类,因此我也为Err了一个。 implicit val format: OFormat[ValidateDetails] = Json.format[ValidateDetails]implicit val format: OFormat[Err] = Json.format[Err]行很神奇,可以为您完成所有读/写操作。

接下来,为您的输出JSON定义一个case类,并定义一个函数,该函数会将您的输入case类变成您的输出类:

object Output {
  case class OutputJson(`ErrorMessages`: Seq[String])

  object OutputJson {
    implicit val format: OFormat[OutputJson] = Json.format[OutputJson]
  }

  // take msg Seq from name & email and add together into single Seq
  def inputToOutput(input: Input.ValidateDetails): OutputJson = {
    OutputJson(input.`obj.name`.flatMap(_.msg) ++ input.`obj.email`.flatMap(_.msg))
  }
}

最后,将其放入映射到您的routes文件中的POST路由的方法中:

def index() = Action { implicit request =>
  val bodyAsJson = request.body.asJson.get
  bodyAsJson.validate[Input.ValidateDetails] match {
    case success: JsSuccess[Input.ValidateDetails] =>
      // turn the JSON into the Output case class and parse that as JSON
      val output: JsValue = Json.toJson(Output.inputToOutput(success.value))
      Ok(output)
    case JsError(error) =>
      BadRequest(JsError.toJson(error))
  }
}

现在,如果您使用以下JSON正文在端口9000上运行Play应用并通过POST到http:// localhost:9000 /

{
    "obj.name": [
        {
          "msg": [
          "error.expected.jsstring"
          ],
          "args": []
        }
    ],
    "obj.email": [
         {
            "msg": [
            "Invalid email"
            ],
            "args": []
         }
    ]
}

...输出将是:

{
    "ErrorMessages": [
        "error.expected.jsstring",
        "Invalid email"
    ]
}

我希望这回答了你的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM