我有一个使用 javax.validation
的 Spring Boot 应用程序注释,我正在尝试返回指向违规字段的友好 JSON 错误消息,但从可用的“Java 对象”路径转换为 JSONPath 或 JSON 指针是我没有找到的方法。
SSCO示例:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import javax.validation.Valid;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.Min;
import java.util.List;
public class Test {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
Data data = new Data();
System.out.println("Serialized: " + mapper.writerWithDefaultPrettyPrinter().writeValueAsString(data));
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
validator.validate(data).forEach(violation -> {
System.out.println("Path: " + violation.getPropertyPath());
});
}
public static class Data {
@JsonProperty("foobar")
@Valid
public List<Foo> foo = List.of(new Foo());
}
public static class Foo {
@Min(100)
public int barBaz = 42;
}
}
输出:Serialized: {
"foobar" : [ {
"bar_baz" : 42
} ]
}
Path: foo[0].barBaz
如您所见,我需要转换 foo[0].barBaz
进入 $.foobar[0].bar_baz
或 /foobar/0/bar_baz
.解析的对象(上面的 data
变量)也由 BindingResult
提供保存验证信息的对象。我想过做一些字符串操作,但这很麻烦,很麻烦,而且很容易被
@JsonProperty
破坏。我需要单独处理,也许是我没有考虑过的其他极端情况。另外,我们使用 SNAKE_CASE
作为一个标准,改变以简化任务不是解决方案。我想 jackson 的
ObjectMapper
可以以某种方式用于进行此转换,或使用其他一些 Jackson API,但我找不到任何相关信息。任何其他可以做到这一点的库也很好(理想情况下它应该理解 Jackson 注释,如 @JsonProperty
)。
最佳答案
您可以使用 Hibernate Validator 6.1.5 轻松完成。
您需要提供自己的 PropertyNodeNameProvider
实现.
By implementing it, we can define how the name of a property will be resolved during validation. In our case, we want to read the value from the Jackson configuration.
创建 validator :
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.propertyNodeNameProvider(new JacksonPropertyNodeNameProvider())
.buildValidatorFactory();
JacksonPropertyNodeNameProvider:public class JacksonPropertyNodeNameProvider implements PropertyNodeNameProvider {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public String getName(Property property) {
if ( property instanceof JavaBeanProperty ) {
return getJavaBeanPropertyName( (JavaBeanProperty) property );
}
return getDefaultName( property );
}
private String getJavaBeanPropertyName(JavaBeanProperty property) {
JavaType type = objectMapper.constructType( property.getDeclaringClass() );
BeanDescription desc = objectMapper.getSerializationConfig().introspect( type );
return desc.findProperties()
.stream()
.filter( prop -> prop.getInternalName().equals( property.getName() ) )
.map( BeanPropertyDefinition::getName )
.findFirst()
.orElse( property.getName() );
}
private String getDefaultName(Property property) {
return property.getName();
}
}
更多详情您可以在 documentation 中找到:
关于java - 从 Spring BindingResult 到字段 JSONPath/JSON Pointer,与 Jackson,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63248487/