使用Play将JSON返回验证错误!骨架

时间:2011-09-29 13:39:44

标签: java ajax json validation playframework

我想构建一个应用程序,通过Ajax提交表单,而无需重新加载页面。要显示服务器端验证错误,服务器应将验证错误作为JSON和适当的HTTP状态返回(400)。

如何通过Play完成此操作!框架?

5 个答案:

答案 0 :(得分:6)

你在寻找比这更复杂的东西:

public static void yourControllerMethod() {
    ... // your validation logic

    if (validation.hasErrors()) {
       response.status = 400;
       renderJSON(validation.errors);
    }
}

答案 1 :(得分:6)

在Play Framework 2.x和Scala中,您可以使用此示例:

import play.api.libs.json._

case class LoginData(email : String, password: String)

implicit object FormErrorWrites extends Writes[FormError] {
  override def writes(o: FormError): JsValue = Json.obj(
    "key" -> Json.toJson(o.key),
    "message" -> Json.toJson(o.message)
  )
}

val authForm = Form[LoginData](mapping(
  "auth.email" -> email.verifying(Constraints.nonEmpty),
  "auth.password" -> nonEmptyText
  )(LoginData.apply)(LoginData.unapply))

def registerUser = Action { implicit request =>
 authForm.bindFromRequest.fold(
  form => UnprocessableEntity(Json.toJson(form.errors)),
  auth => Ok(Json.toJson(List(auth.email, auth.password)))
 )
}

我看到这个问题标有java标签,但我想这可能对Scala开发人员有用。

答案 2 :(得分:5)

为了对您的请求执行服务器端验证,Play框架提供了内置验证模块,该模块使用了Hibernate Validator

假设您有一个与传入请求相对应的POJO类,

import play.data.validation.Constraints;
    public class UserRequest{       
    @Constraints.Required
    private String userName;

    @Constraints.Required
    private String email;
}

请求验证可以从控制器执行,如下所示。

public class UserController extends Controller{
Form<UserRequest> requestData = Form.form(UserRequest.class).bindFromRequest();
    if(requestData.hasErrors()){
        return badRequest(requestData.errorsAsJson());
    } else{
        //... successful validation
    }
}

如果请求未通过验证,将产生以下响应。

{
  "userName": [
    "This field is required"
  ],
  "email": [
    "This field is required"
  ]
}

除此之外,您还可以将多个约束应用于类字段。其中一些是,

  • @ Constraints.Min()
  • @ Constraints.Max()
  • @ Constraints.Email

答案 3 :(得分:4)

查看samples-and-tests文件夹和验证应用程序。其中一个示例(Sample7)使用名为jQueryValidate的自定义标记(您可以在示例中看到)完成您所使用的操作。

如果你试试这个样本,你会发现它是一个非常简洁的解决方案,在我看来,这个验证方法应该是Core Play框架的一部分。

答案 4 :(得分:0)

由于您提到了[java]标签,因此我暗示您使用Java版本的Play框架。此外,我看不到任何前提条件指向无法使用任何第三方库。基于此,您可以使用validol验证库,以鼓励declarative style

请考虑以下请求,该请求可以是一种注册请求,但是为了简洁起见,它由单个payment块组成:

{
    "payment":{
        "card_number":12345612341234,
        "expires_at":"12/29"
    }
}

验证逻辑是单个不变的表达式,表示为一个类:

public class ValidatedRegistrationRequest implements Validatable<RegistrationRequest>
{
    private String jsonRequestString;
    private Connection dbConnection;

    public ValidatedRegistrationRequest(String jsonRequestString, Connection dbConnection)
    {
        this.jsonRequestString = jsonRequestString;
        this.dbConnection = dbConnection;
    }

    @Override
    public Result<RegistrationRequest> result() throws Exception
    {
        return
            new FastFail<>(
                new WellFormedJson(
                    new Unnamed<>(Either.right(new Present<>(this.jsonRequestString)))
                ),
                requestJsonObject ->
                    new UnnamedBlocOfNameds<>(
                        List.of(
                            new FastFail<>(
                                new IsJsonObject(
                                    new Required(
                                        new IndexedValue("payment", requestJsonObject)
                                    )
                                ),
                                paymentJsonObject ->
                                    new NamedBlocOfNameds<>(
                                        "payment",
                                        List.of(
                                            new ValidThrueIsNotExpired(
                                                new AsString(
                                                    new Required(
                                                        new IndexedValue("valid_thru", paymentJsonObject)
                                                    )
                                                )
                                            ),
                                            new CardNumberIsNotBlacklisted(
                                                new CardNumberSatisfiesLuhnAlgorithm(
                                                    new Required(
                                                        new IndexedValue("card_number", paymentJsonObject)
                                                    )
                                                ),
                                                this.dbConnection
                                            )
                                        ),
                                        Payment.class
                                    )
                            )
                        ),
                        RegistrationRequest.class
                    )
            )
                .result()
            ;
    }
}

在SO上没有显示行号的简便方法,但这是上面代码的line-by-line analysis

与JSON Schema相比,这种方法通常只需要较少的行,并且在用于非常复杂的请求时才真正发光。