gpt4 book ai didi

java - 使用自定义 Json 输出在 DropWizard 中进行 Bean 验证

转载 作者:行者123 更新时间:2023-12-02 02:52:52 25 4
gpt4 key购买 nike

我正在开发一个具有各种 Rest 功能的网络服务。我想使用标准 @Valid 注释来验证我的 bean。但是我确实想修改输出 json 错误。

验证中的错误消息当前格式如下:

{
"errors": [
"someString size must be between 0 and 140",
"anotherString cannot contain numbers"
]
}

但是我确实希望错误消息的格式如下:

{
"errors": [{
"someString": "size must be between 0 and 140"
},
{
"anotherString": "cannot contain numbers"
}
]
}

{
"errors": [{
"field": "someString"
"error": "size must be between 0 and 140"
},
{
"field": "anotherString"
"error": "cannot contain numbers"
}
]
}

我知道如何通过向验证注释提供 message="some message about strings" 来更改错误消息,甚至使用 ValidationMEssages.properties作为所有错误消息的公共(public)位置。然而,如果发生错误,我不知道如何更改输出格式。

我已阅读以下文档,但我需要更多指导。 http://www.dropwizard.io/1.0.0/docs/manual/validation.html

这是我的第一个DropWizard项目,我习惯在Spring中开发。

提前致谢。

最佳答案

我找到了解决我自己问题的方法。如果有人遇到和我一样的问题,我决定将其发布。

这是针对 DropWizard 1.0 的,我尚未测试它是否适用于早期/更高版本,因此请记住这一点。我无法为您提供完整的解决方案,但我已经发布了我的解决方案是代码片段,因此不要指望您可以简单地复制/粘贴并编译。

解决方案实际上非常简单,您只需为 ConstraintViolationException 实现自己的 ExceptionMapper 并使用 DropWizard 重新注册即可。

您可以通过提供模板或常规文本轻松指定自己的 Bean 验证消息。 IE。

@NotNull(message="该死的,莫蒂。我要求你做一件事!")

@NotNull(message="{morty.error}")

模板位于 ValidationMessages.properties 中,您必须自己创建并放置在 src/main/resources/

ValidationMessages.properties

morty.error=God damn it, Morty. I ask you to do one thing!

无论如何,这是我的解决方案。

SomeApplication.class

//Class where you setup DropWizard
public class SomeApplication extends Application<SomeConfiguration> {

@Override
public void run(SomeConfiguration conf, Environment environment) throws Exception {

//Remove all default ExceptionMappers
((DefaultServerFactory)conf.getServerFactory()).setRegisterDefaultExceptionMappers(false);

//Register your custom ExceptionMapper for ConstraintViolationException
environment.jersey().register(new CustomExceptionMapper());

//Restore the default ExceptionsMappers that you just removed
environment.jersey().register(new LoggingExceptionMapper<Throwable>() {});
environment.jersey().register(new JsonProcessingExceptionMapper());
environment.jersey().register(new EarlyEofExceptionMapper());
}
}

CustomExceptionMapper.class

//This is where the magic happens. 
//This is your custom ExceptionMapper for ConstraintViolationException
@Provider
public class CustomExceptionMapper implements ExceptionMapper<ConstraintViolationException> {

@Override
public Response toResponse(ConstraintViolationException cve) {
//List to store all the exceptions that you whish to output
//ValidationErrors is a custom object, which you can see further down
ValidationErrors validationErrors = new ValidationErrors();

//Loop through all the ConstraintViolations
for(ConstraintViolation<?> c : cve.getConstraintViolations()){

//We retrieve the variable name or method name where the annotation was called from.
//This will be your property name for your JSON output.
String field = ((PathImpl)c.getPropertyPath()).getLeafNode().getName();

//If field is null, then the notation is probably at a class level.
//Set field to class name
if(field == null){
field = c.getLeafBean().getClass().getSimpleName();
}

//c.getMessage() is the error message for your annotation.
validationErrors.add(field, c.getMessage());
}
//Return a response with proper http status.
return Response.status(422).entity(validationErrors).build();
}
}

验证错误

//There is not really any magic happening here.
//This class is just a wrapper for a List with the type ValidationObject.
public class ValidationErrors {

public List<ValidationObject> errors = new ArrayList<ValidationObject>();

public void add(String field, String error){
errors.add(new ValidationObject(field, error));
}
}

ValidationObject.class

//Once again, no magic
public class ValidationObject {

//This will be your property names
private String field, error;

public ValidationObject(String field, String error){
this.field = field;
this.error = error;
}

public String getField() {
return field;
}

public void setField(String field) {
this.field = field;
}

public String getError() {
return error;
}

public void setError(String error) {
this.error = error;
}
}

TestClass.class

//This is just a class to showcase the functionality
//I have not posted any codesnippers for this @CustomClassConstaint,
//it is a custom annotaiton.
//I only included this annotation to show how
//the CustomExceptionMapper handles annotations on a class level
@CustomClassConstaint
public class TestClass {

@NotNull
@Size(min = 2, max = 5)
public String testString1;

@NotNull
@Size(min = 2, max = 5)
public String testString2;

@Min(10)
@Max(20)
public int testInt1;

@Min(10)
@Max(20)
public int testInt2;

}

用于测试的休息功能

    //Some rest function to showcase
@POST
@Path("/path/to/test")
//Remember @Valid or annotations will not be validated
public Response callRestTestMethod(@Valid TestClass testObject){
return Response.ok().build();
}

测试输入:

POST /path/to/test
{
"testString1": null,
"testString2": "",
"testInt1": 9,
"testInt2": 21
}

测试输出:

顺序有些随机,并且每次调用 callRestTestMethod(...) 时都会发生变化。验证按照组件树中的顺序一一触发,不知道是否可以控制顺序。

{
"errors": [
{
"field": "TestClass",
"error": "custom error msg"
},
{
"field": "testInt1",
"error": "must be greater than or equal to 10"
},
{
"field": "testString1",
"error": "may not be null"
},
{
"field": "testInt2",
"error": "must be less than or equal to 20"
},
{
"field": "testString2",
"error": "size must be between 2 and 5"
}
]
}

关于java - 使用自定义 Json 输出在 DropWizard 中进行 Bean 验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43542667/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com