Custom JSON validation constraints in Play Framework 2.3 (Scala)

前端 未结 1 1768
日久生厌
日久生厌 2021-02-07 23:18

I managed to implement form validation with custom constraints, but now I want to do the same thing with JSON data.

How can I apply custom validation rules to a JSON par

相关标签:
1条回答
  • 2021-02-07 23:51

    The simplest way I can think of would use the filter method from Reads.

    Let's say we have some User object that will determine if the user name exists:

    object User {
        def findByName(name: String): Option[User] = ...
    }
    

    You could then construct your Reads like this:

    import play.api.libs.json._
    import play.api.libs.functional.syntax._
    import play.api.data.validation._
    
    case class ExampleCaseClass(username: String, somethingElse: String)
    
    object ExampleCaseClass {
        implicit val exampleReads: Reads[ExampleCaseClass] = (
            (JsPath \ "username").read[String].filter(ValidationError("User does not exist."))(findByName(_).isDefined) and
            (JsPath \ "somethingElse").read[String]
        )(ExampleCaseClass.apply _)
    }
    

    Your controller function can be simplified using a json BodyParser and fold:

    def postNew = Action(parse.json) { implicit request =>
        request.body.validate[ExampleCaseClass].fold(
            error => BadRequest(JsError.toFlatJson(error)),
            obj => {
                // Do something with the validated object..
            }
        )
    }
    

    You could also create a separate Reads[String] that will check if the user exists, and explicitly use that Reads[String] within your Reads[ExampleCaseClass]:

    val userValidate = Reads.StringReads.filter(ValidationError("User does not exist."))(findByName(_).isDefined)
    
    implicit val exampleReads: Reads[ExampleCaseClass] = (
        (JsPath \ "username").read[String](userValidate) and
        (JsPath \ "somethingElse").read[String]
    )(ExampleCaseClass.apply _)
    
    0 讨论(0)
提交回复
热议问题