我想构建一个应用程序,通过Ajax提交表单,而无需重新加载页面。要显示服务器端验证错误,服务器应将验证错误作为JSON和适当的HTTP状态返回(400)。
如何通过Play完成此操作!框架?
答案 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"
]
}
除此之外,您还可以将多个约束应用于类字段。其中一些是,
答案 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相比,这种方法通常只需要较少的行,并且在用于非常复杂的请求时才真正发光。