Restrições de validação JSON personalizadas no Play Framework 2.3 (Scala)

Consegui implementar a validação de formulário com restrições personalizadas, mas agora quero fazer o mesmo com os dados JSON.

Como posso aplicar regras de validação personalizadas a um analisador JSON?

Exemplo: a solicitação POST do cliente contém um nome de usuário (username) e não apenas quero garantir que esse parâmetro seja um texto não vazio, mas também que esse usuário realmente exista no banco de dados.

// 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 _)
}

Isso é o mais longe que eu chego, mas isso só garante queusername é uma string.Como aplico minha regra de validação personalizada adicional, por exemplo. verificar se o usuário fornecido realmente existe? Isso é possível?

Claro, eu poderia pegar minhaobj nocase success na ação e execute verificações adicionais lá, mas isso não parece muito elegante, porque então eu teria que criar minha própria mensagem de erro e só poderia usar o usuárioJsError.toFlatJson(error) para alguns casos. Depois de pesquisar e tentar por horas, não consegui encontrar nenhum exemplo.

Para formulários regulares, eu usaria algo como isto:

// 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!")
    }
)

Mas e se os dados forem enviados como JSON?

questionAnswers(1)

yourAnswerToTheQuestion