Java Jackson反序列化错误处理
我的问题相当简单:我有以下简单的类:Java Jackson反序列化错误处理,java,json,deserialization,jackson,Java,Json,Deserialization,Jackson,我的问题相当简单:我有以下简单的类: public class Foo { private int id = -1; public void setId(int _id){ this.id = _id; } public int getId(){ return this.id; } } 我正在尝试处理以下JSON: { "id": "blah" } 显然,这里有一个问题(“blah”不能解析为int) 以前,Jackson抛出类似org.codehaus.Jackson
public class Foo {
private int id = -1;
public void setId(int _id){ this.id = _id; }
public int getId(){ return this.id; }
}
我正在尝试处理以下JSON:
{
"id": "blah"
}
显然,这里有一个问题(“blah”不能解析为int)
以前,Jackson抛出类似org.codehaus.Jackson.map.JsonMappingException的内容:无法从字符串值“blah”构造java.lang.Integer的实例:不是有效的整数值
我同意这一点,但我想注册一些可以忽略这种映射错误的地方。
我尝试使用已注册的反序列化ProblemHandler(请参阅),但它似乎只适用于未知属性,而不适用于反序列化问题
你对这个问题有什么线索吗?多亏了你,我成功地解决了我的问题 我必须为Jackson中处理的每个基本类型使用自定义非阻塞反序列化器。 类似于这个工厂:
public class JacksonNonBlockingObjectMapperFactory {
/**
* Deserializer that won't block if value parsing doesn't match with target type
* @param <T> Handled type
*/
private static class NonBlockingDeserializer<T> extends JsonDeserializer<T> {
private StdDeserializer<T> delegate;
public NonBlockingDeserializer(StdDeserializer<T> _delegate){
this.delegate = _delegate;
}
@Override
public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
try {
return delegate.deserialize(jp, ctxt);
}catch (JsonMappingException e){
// If a JSON Mapping occurs, simply returning null instead of blocking things
return null;
}
}
}
private List<StdDeserializer> jsonDeserializers = new ArrayList<StdDeserializer>();
public ObjectMapper createObjectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule customJacksonModule = new SimpleModule("customJacksonModule", new Version(1, 0, 0, null));
for(StdDeserializer jsonDeserializer : jsonDeserializers){
// Wrapping given deserializers with NonBlockingDeserializer
customJacksonModule.addDeserializer(jsonDeserializer.getValueClass(), new NonBlockingDeserializer(jsonDeserializer));
}
objectMapper.registerModule(customJacksonModule);
return objectMapper;
}
public JacksonNonBlockingObjectMapperFactory setJsonDeserializers(List<StdDeserializer> _jsonDeserializers){
this.jsonDeserializers = _jsonDeserializers;
return this;
}
}
您可能希望通过添加处理此特定异常的方法,让控制器处理此问题
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseBody
public String handleHttpMessageNotReadableException(HttpMessageNotReadableException ex)
{
JsonMappingException jme = (JsonMappingException) ex.getCause();
return jme.getPath().get(0).getFieldName() + " invalid";
}
当然,这条线
JsonMappingException jme = (JsonMappingException) ex.getCause();
可能会对某些情况引发类强制转换异常,但我还没有遇到它们。创建一个简单的映射程序:
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JSONProcessingErroMapper implements ExceptionMapper<InvalidFormatException> {
@Override
public Response toResponse(InvalidFormatException ex) {
return Response.status(400)
.entity(new ClientError("[User friendly message]"))
.type(MediaType.APPLICATION_JSON)
.build();
}
@Provider
@产生(MediaType.APPLICATION_JSON)
公共类JSONProcessingErrorMapper实现ExceptionMapper{
@凌驾
公众回应(无效形式例外){
返回响应。状态(400)
.entity(新的ClientError(“[用户友好消息]”)
.type(MediaType.APPLICATION_JSON)
.build();
}
}我编写了一个简单的错误处理程序,它会给您一些错误,您可以将错误请求作为状态代码返回给用户。使用@JsonProperty required=true获取与缺少的属性相关的错误。杰克逊版本2.9.8
public class JacksonExceptionHandler {
public String getErrorMessage(HttpMessageNotReadableException e) {
String message = null;
boolean handled = false;
Throwable cause = e.getRootCause();
if (cause instanceof UnrecognizedPropertyException) {
UnrecognizedPropertyException exception = (UnrecognizedPropertyException) cause;
message = handleUnrecognizedPropertyException(exception);
handled = true;
}
if (cause instanceof InvalidFormatException) {
InvalidFormatException exception = (InvalidFormatException) cause;
message = handleInvalidFormatException(exception);
handled = true;
}
if (cause instanceof MismatchedInputException) {
if (!handled) {
MismatchedInputException exception = (MismatchedInputException) cause;
message = handleMisMatchInputException(exception);
}
}
if (cause instanceof JsonParseException) {
message = "Malformed json";
}
return message;
}
private String handleInvalidFormatException(InvalidFormatException exception) {
String reference = null;
if (!exception.getPath().isEmpty()) {
String path = extractPropertyReference(exception.getPath());
reference = removeLastCharacter(path);
}
Object value = exception.getValue();
return "Invalid value '" + value + "' for property : " + reference;
}
private String handleUnrecognizedPropertyException(UnrecognizedPropertyException exception) {
String reference = null;
if (!exception.getPath().isEmpty()) {
String path = extractPropertyReference(exception.getPath());
reference = removeLastCharacter(path);
}
return "Unknown property : '" + reference + "'";
}
private String handleMisMatchInputException(MismatchedInputException exception) {
String reference = null;
if (!exception.getPath().isEmpty()) {
reference = extractPropertyReference(exception.getPath());
}
String property = StringUtils.substringBetween(exception.getLocalizedMessage(), "'", "'");
// if property missing inside nested object
if (reference != null && property!=null) {
return "Missing property : '" + reference + property + "'";
}
// if invalid value given to array
if(property==null){
return "Invalid values at : '"+ reference +"'";
}
// if property missing at root level
else return "Missing property : '" + property + "'";
}
// extract nested object name for which property is missing
private String extractPropertyReference(List<JsonMappingException.Reference> path) {
StringBuilder stringBuilder = new StringBuilder();
path.forEach(reference -> {
if(reference.getFieldName() != null) {
stringBuilder.append(reference.getFieldName()).append(".");
// if field is null means it is array
} else stringBuilder.append("[].");
}
);
return stringBuilder.toString();
}
// remove '.' at the end of property path reference
private String removeLastCharacter(String string) {
return string.substring(0, string.length() - 1);
}
}
公共类JacksonExceptionHandler{
公共字符串getErrorMessage(HttpMessageGenetradableException e){
字符串消息=null;
布尔值=假;
可丢弃原因=e.getRootCause();
if(导致实例发生无法识别的属性异常){
UnrecognizedPropertyException异常=(UnrecognizedPropertyException)原因;
message=handleUnrecognedPropertyException(异常);
已处理=正确;
}
如果(导致InvalidFormatException实例){
InvalidFormatException异常=(InvalidFormatException)原因;
message=handleInvalidFormatException(异常);
已处理=正确;
}
if(导致实例不匹配InputException){
如果(!已处理){
MismatchedInputException异常=(MismatchedInputException)原因;
消息=handleMisMatchInputException(异常);
}
}
if(导致JsonParseException实例){
message=“格式错误的json”;
}
返回消息;
}
私有字符串handleInvalidFormatException(InvalidFormatException异常){
字符串引用=null;
如果(!exception.getPath().isEmpty()){
字符串路径=extractPropertyReference(exception.getPath());
reference=removeLastCharacter(路径);
}
对象值=exception.getValue();
为属性“+引用”返回“无效值”'+值+”;
}
私有字符串handleUnrecognizedPropertyException(UnrecognizedPropertyException){
字符串引用=null;
如果(!exception.getPath().isEmpty()){
字符串路径=extractPropertyReference(exception.getPath());
reference=removeLastCharacter(路径);
}
返回“未知属性:'”+引用+'”;
}
私有字符串HandleMistMatchInputException(不匹配InputException异常){
字符串引用=null;
如果(!exception.getPath().isEmpty()){
reference=extractPropertyReference(exception.getPath());
}
String属性=StringUtils.substringBetween(exception.getLocalizedMessage(),“',”);
//如果嵌套对象中缺少属性
if(reference!=null&&property!=null){
返回“缺少属性:”+“引用+属性+””;
}
//如果给数组的值无效
if(属性==null){
返回“无效值位于:'”+引用+'”;
}
//如果根级别缺少属性
否则返回“缺少属性:'”+“属性+”;
}
//提取缺少属性的嵌套对象名称
私有字符串提取属性引用(列表路径){
StringBuilder StringBuilder=新的StringBuilder();
path.forEach(参考->{
if(reference.getFieldName()!=null){
stringBuilder.append(reference.getFieldName()).append(“.”);
//若字段为空,则表示它是数组
}else stringBuilder.追加(“[]”);
}
);
返回stringBuilder.toString();
}
//删除属性路径引用末尾的“.”
私有字符串removeLastCharacter(字符串){
返回string.substring(0,string.length()-1);
}
}
在全局通知中调用这个类对象,如下所示
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
String message = new JacksonExceptionHandler().generator.getErrorMessage(ex);
if(message == null){
return ResponseEntity.badRequest().body("Malformed json");
}
return ResponseEntity.badRequest().body(message);
}
@覆盖
受保护的ResponseEntity HandleHttpMessageGenoTreadable(HttpMessageGenoTreadableException ex、HttpHeaders标头、HttpStatus状态、WebRequest请求){
字符串消息=新JacksonExceptionHandler().generator.getErrorMessage(ex);
如果(消息==null){
返回ResponseEntity.badRequest().body(“格式错误的json”);
}
返回ResponseEntity.badRequest().body(消息);
}
为什么要忽略此错误?我会将HTTP代码400
返回给每个试图给我这样的资源表示的客户机:)我正在使用Jackson进行Spring MVC和bean验证。问题是杰克逊是一名康普
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
String message = new JacksonExceptionHandler().generator.getErrorMessage(ex);
if(message == null){
return ResponseEntity.badRequest().body("Malformed json");
}
return ResponseEntity.badRequest().body(message);
}