子对象上的 javax.validation.valid

shh*_*hha 6 java validation methods spring

我有一个简单的结构

public class Parent {
    @Size(min = 5, max = 10)
    String lastName;
    List<Child> childs;
}

public class Child {
    @Size(min = 5, max = 10)
    String firstName;
    @Size(min = 1, max = 18)
    Integer age;
}
Run Code Online (Sandbox Code Playgroud)

和一个有定义的方法

@ResponseBody
@RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces="application/json")
public RestResponse create(@RequestBody Parent object)
Run Code Online (Sandbox Code Playgroud)

它创建(并提供更新)父对象。

假设我想创建两个功能:

1) 创建工作副本 - 用户不必正确插入所有数据。

2)向我发送这些数据 - 在这个例子中,我想验证它们是否正确。

我发现有一种方法可以通过向方法定义中的参数添加 @Valid 注释来验证它,如下所示:

@ResponseBody
@RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces="application/json")
public RestResponse create(@RequestBody @Valid Parent object)
Run Code Online (Sandbox Code Playgroud)

但它只对父字段有效,跳过子字段。我可以在子列表上添加 @Valid 注释:

public class Parent {
    @Size(min = 5, max = 10)
    String lastName;
    List<Child> childs;
}
Run Code Online (Sandbox Code Playgroud)

但它会一直工作 - 即使我想保存工作副本。是否可以有条件地使父对象内的对象有效?

小智 5

您可以使用验证组。在这种情况下,您的模型可能如下所示:

public class Parent {

    @Size(min = 5, max = 10, groups = { Draft.class, FinalVersion.class })
    String lastName;
    @Valid
    List<Child> childs;
}

public class Child {

    @Size(min = 5, max = 10, groups = FinalVersion.class)
    String firstName;
    @Range(min = 1, max = 18, groups = FinalVersion.class)
    Integer age;

}
Run Code Online (Sandbox Code Playgroud)

另请注意@SizeInteger 类型不支持 - 您可能想要使用其中一个@Range或一对@Min @Max(本质上是相同的)。 Draft并且FinalVersion只是简单的接口,用于定义验证组:

interface Draft {
}

interface FinalVersion {
}
Run Code Online (Sandbox Code Playgroud)

然后在您的控制器中,您需要@Validated在 bean 参数上使用而不是@Valid,因为第一个允许您选择验证组。所以你的控制器看起来像:

@ResponseBody
@RequestMapping(value = "saveDraft", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
public RestResponse create(@RequestBody @Validated(Draft.class) Parent object) {
    // your stiff here
}

@ResponseBody
@RequestMapping(value = "submitFinal", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
public RestResponse create(@RequestBody @Validated(FinalVersion.class) Parent object) {
    // your stiff here
}
Run Code Online (Sandbox Code Playgroud)

但是您需要有两种方法来处理帖子 - 一种用于草稿,一种用于最终提交。


小智 5

只需将 @Valid 添加到您的 childList 中,它应该可以工作

public class Parent {
@Size(min = 5, max = 10)
String lastName;
@Valid
List<Child> childs;
Run Code Online (Sandbox Code Playgroud)

}


Sta*_*avL 0

我会添加@Valid并始终验证它。如果您不关心有效的子项,您可以添加BindingResult bindingResult到控制器方法以防止默认验证,并通过错误列表忽略无效的子项。

使用bindingResult.hasFieldErrors(fieldName)方法。

或者您可以创建另一个扩展 Parent 的 ParentExt 并添加@Validgetter 而不是字段。