使用 Play 以 JSON 形式返回验证错误!框架

Posted

技术标签:

【中文标题】使用 Play 以 JSON 形式返回验证错误!框架【英文标题】:Returning validation errors as JSON with Play! framework 【发布时间】:2011-11-27 17:32:36 【问题描述】:

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

如何通过 Play 实现这一点!框架?

【问题讨论】:

【参考方案1】:

您是否正在寻找比这更复杂的东西:

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

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

【讨论】:

【参考方案2】:

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

如果你尝试这个示例,你会发现它是一个非常简洁的解决方案,在我看来,这种验证方法应该是 Core Playframework 的一部分。

【讨论】:

【参考方案3】:

在 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 开发人员有用。

【讨论】:

上述的导入语句应该包括import play.api.libs.json._,并且当您转换表单错误时,隐式对象很可能作为可重用实体存在于您的控制器中(注意表单点错误)而不是任何东西案例类本身独有。一旦你知道了这一切,那就很明显了,但 *** 可以帮助那些不知道的人:) 感谢提示,我已添加导入。【参考方案4】:

为了对您的请求执行服务器端验证,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

【讨论】:

【参考方案5】:

既然您提到了[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 相比,这种方法通常需要更少的行,并且在用于非常复杂的请求时确实非常出色。

【讨论】:

以上是关于使用 Play 以 JSON 形式返回验证错误!框架的主要内容,如果未能解决你的问题,请参考以下文章

以 json 形式返回部分视图?

Struts2中如何将验证的错误信息用提示框的形式显示出来?

以简单的形式获取 error_notification 文本而不生成验证错误

如何以 json laravel 的形式返回分页

使用 websocketpp 以 json 形式返回的数据,但使用 messagepack 以 Blob 形式返回的数据

角度反应形式 - 验证变化和模糊两者