Restricciones de validación JSON personalizadas en Play Framework 2.3 (Scala)

Logré implementar la validación de formularios con restricciones personalizadas, pero ahora quiero hacer lo mismo con los datos JSON.

¿Cómo puedo aplicar reglas de validación personalizadas a un analizador JSON?

Ejemplo: la solicitud POST del cliente contiene un nombre de usuario (username) y no solo quiero asegurarme de que este parámetro sea un texto no vacío, sino que este usuario realmente exista en la base de datos.

// In the controller...

def postNew = Action { implicit request =>
    request.body.asJson.map { json =>
        json.validate[ExampleCaseClass] match {
            case success: JsSuccess[ExampleCaseClass] =>
                val obj: ExampleCaseClass = success.get
                // ...do something with obj...
                Ok("ok")
            case error: JsError =>
                BadRequest(JsError.toFlatJson(error))
        }
    } getOrElse(BadRequest(Json.obj("msg" -> "JSON request expected")))
}


// In ExampleCaseClass.scala...

case class ExampleCaseClass(username: String, somethingElse: String)

object ExampleCaseClass {
    // That's what I would use for a form:
    val userCheck: Mapping[String] = nonEmptyText.verifying(userExistsConstraint)

    implicit val exampleReads: Reads[ExampleCaseClass] = (
        (JsPath \ "username").read[String] and
        (JsPath \ "somethingElse").read[String]
    )(ExampleCaseClass.apply _)
}

Eso es lo que llego, pero esto solo asegura queusername es una cadena¿Cómo aplico mi regla de validación personalizada adicional?, p.ej. verificar si el usuario dado realmente existe? ¿Es esto posible?

Claro, podría tomar miobj en elcase success sección en la acción y realizar verificaciones adicionales allí, pero esto no parece muy elegante, porque entonces tendría que crear mi propio mensaje de error y solo podríaJsError.toFlatJson(error) para algunos casos Después de buscar e intentar durante horas, no pude encontrar ningún ejemplo.

Para formularios regulares, usaría algo como esto:

// In the controller object...

val userValidConstraint: Constraint[String] = Constraint("constraints.uservalid")({ username =>
    if (User.find(username).isDefined) {
        Valid
    } else {
        val errors = Seq(ValidationError("User does not exist"))
        Invalid(errors)
    }
})

val userCheck: Mapping[String] = nonEmptyText.verifying(userValidConstraint)

val exampleForm = Form(
    mapping(
        "username" -> userCheck
        // ...and maybe some more fields...
    )(ExampleCaseClass.apply)(ExampleCaseClass.unapply)
)


// In the controller's action method...

exampleForm.bindFromRequest.fold(
    formWithErrors => {
        BadRequest("Example error message")
    },
    formData => {
        // do something
        Ok("Valid!")
    }
)

Pero, ¿qué pasa si los datos se envían como JSON?

Respuestas a la pregunta(1)

Su respuesta a la pregunta