如何使用杰克逊反序列化中的自定义反序列化传递自定义错误消息

时间:2016-11-04 17:17:04

标签: java json jackson json-deserialization fasterxml

我有一个pojo类,其中一个标志是isControl,其类型为Boolean。

当此属性获取非布尔值而非true或false时,fastxml jackson会自动将输入值转换为true。所以我按照Jackson Deserialize custom boolean json property

编写了Custom Deserializer类

为了向调用者显示自定义错误消息,我编写了自己的错误消息类,其中显示了自定义消息(注意:我无法通过Jackson反序列化程序显示自定义错误消息,&& #39;为什么我编写自己的Exception类来显示自定义消息)

但我现在的问题是当控件返回到setter方法时它包含null值,如果输入错误,Jackson会在我的控制台日志中抛出异常。我想在日志中抑制这个异常,但是如果我保留一个catch块,那么实际的事务就会被传递。

绝对应该有更好的方法来显示自定义错误消息,以防错误输入boolen字段。我不想将我的布尔字段数据类型更改为Object因为我需要在很多地方改变代码。 请建议。

Control.java

@JsonDeserialize(using = BooleanKeyDeserializer.class)

private Boolean isControlEnabled;
public Boolean getIsControlEnabled() {
        return isControlEnabled;
    }

public void setIsControlEnabled(Boolean isControlEnabled) throws BadRequestException {
        System.out.println("------before setIsControlEnabled##: " + isControlEnabled);
        if (isControlEnabled instanceof Boolean) {              
                this.isControlEnabled =((Boolean)isControlEnabled).booleanValue();
        }else{
                throw new BadRequestException("boolean field should be either true|false");//Exception is getting thrown here since BooleanKeyDeserializer returns null value for wrong input
        }

BooleanKeyDeserializer.java

public class BooleanKeyDeserializer extends JsonDeserializer<Boolean>{

    public static final Logger log = LoggerFactory
            .getLogger(BooleanKeyDeserializer.class);
final protected Class<?> _valueClass = Boolean.class;

    @Override
    public Boolean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
            JsonProcessingException {
        try {
            return _parseBooleanPrimitive2(jp, ctxt);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            //e.printStackTrace();
            log.debug("Wrong input is passed for a boolean field");
        }
        return null;
    }

    protected final boolean _parseBooleanPrimitive2(JsonParser jp, DeserializationContext ctxt)
            throws Exception {
        System.out.println("----------Parse Boolean------------");
        JsonToken t = jp.getCurrentToken();

        if (t == JsonToken.VALUE_TRUE) {
            return true;
        }
        if (t == JsonToken.VALUE_FALSE) {
            return false;
        }        
        if (t == JsonToken.VALUE_NUMBER_INT) {         
          throw new BadRequestException("control flag should be either true|false");
        }
        if (t == JsonToken.VALUE_NULL) {
            throw new BadRequestException("control flag should be either true|false");
        }
        if (t == JsonToken.VALUE_STRING) {
            String text = jp.getText().trim();
            if ("true".equalsIgnoreCase(text)) {
                return true;
            }
            if ("false".equalsIgnoreCase(text) || text.length() == 0) {
                return Boolean.FALSE;
            }            
            throw ctxt.weirdStringException(text, _valueClass, "control flag should be true|false");
        }
        if(!t.isBoolean()){
            throw new BadRequestException("control flag should be either true|false");
        }
        // Otherwise, no can do:
        throw ctxt.mappingException(_valueClass);
    }

    @Override
    public Boolean getNullValue(DeserializationContext ctxt) {
        throw new BadRequestException("control flag should be either true|false");
    }

控制台日志:

----------Parse Boolean------------
10:34:51.501 [tomcat-http--32] DEBUG c.v.i.v.d.v.BooleanKeyDeserializer - Wrong input is passed for a boolean field
10:35:21.908 [tomcat-http--32] DEBUG o.s.w.s.m.m.a.ServletInvocableHandlerMethod - Error resolving argument [0] 
org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: boolean field should be either true|false (through reference chain: 
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:229) ~[spring-web-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:213) ~[spring-web-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:197) ~[spring-webmvc-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:147) ~[spring-webmvc-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:125) ~[spring-webmvc-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:99) ~[spring-web-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:161) [spring-web-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) [spring-web-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) [spring-webmvc-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:832) [spring-webmvc-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:743) [spring-webmvc-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) [spring-webmvc-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:961) [spring-webmvc-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895) [spring-webmvc-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967) [spring-webmvc-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869) [spring-webmvc-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) [servlet-api.jar:na]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843) [spring-webmvc-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [servlet-api.jar:na]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292) [catalina.jar:na]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:na]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-websocket.jar:8.0.33.A]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [catalina.jar:na]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:na]
    at com.visa.ip.vctc.services.logging.PerformanceFilterNonRealTime.doFilterInternal(PerformanceFilterNonRealTime.java:55) [ip_vctc_services-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [catalina.jar:na]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:na]
    at com.visa.ip.vctc.services.logging.CorrelationLoggingFilter.doFilterInternal(CorrelationLoggingFilter.java:58) [ip_vctc_services-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [catalina.jar:na]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [catalina.jar:na]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) [catalina.jar:na]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [catalina.jar:na]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [catalina.jar:na]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) [catalina.jar:na]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [catalina.jar:na]
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) [catalina.jar:na]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [catalina.jar:na]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522) [catalina.jar:na]
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095) [tomcat-coyote.jar:8.0.33.A]
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672) [tomcat-coyote.jar:8.0.33.A]
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:277) [tomcat-coyote.jar:8.0.33.A]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_101]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_101]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.0.33.A]
    at java.lang.Thread.run(Unknown Source) [na:1.8.0_101]
Caused by: com.fasterxml.jackson.databind.JsonMappingException: boolean field should be either true|false (through reference chain: 
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:564) ~[jackson-databind-2.6.3.jar:2.6.3]
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:548) ~[jackson-databind-2.6.3.jar:2.6.3]
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:99) ~[jackson-databind-2.6.3.jar:2.6.3]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:339) ~[jackson-databind-2.6.3.jar:2.6.3]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133) ~[jackson-databind-2.6.3.jar:2.6.3]
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520) ~[jackson-databind-2.6.3.jar:2.6.3]
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95) ~[jackson-databind-2.6.3.jar:2.6.3]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:339) ~[jackson-databind-2.6.3.jar:2.6.3]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133) ~[jackson-databind-2.6.3.jar:2.6.3]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736) ~[jackson-databind-2.6.3.jar:2.6.3]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2810) ~[jackson-databind-2.6.3.jar:2.6.3]
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:226) ~[spring-web-4.2.8.RELEASE.jar:4.2.8.RELEASE]
    ... 46 common frames omitted
Caused by: com.xxxxxxx.BadRequestException: boolean field should be either true|false
    at com.xxxxxxxx.Control.setIsControlEnabled(Control.java:141) ~[xxxxxxxx]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_101]
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_101]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_101]
    at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_101]
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:97) ~[jackson-databind-2.6.3.jar:2.6.3]
    ... 55 common frames omitted

0 个答案:

没有答案