• Jackson工具类解析异常Illegal unquoted character ((CTRLCHAR, code 26))


    在介绍异常之前,先贴出写的工具类吧,毕竟空谈无用嘛。
    public class JacksonUtil {
       private static Logger logger = LoggerFactory.getLogger(JacksonUtil.class);
    
        private final static ObjectMapper OBJ_MAPPER = new ObjectMapper();
        public static ObjectMapper getInstance() {
            return OBJ_MAPPER;
        }
    
        /**
         * bean、array、List、Map --> json
         * 
         * @param obj
         * @return json string
         * @throws Exception
         */
        public static String writeValueAsString(Object obj) {
           try {
             return getInstance().writeValueAsString(obj);
          } catch (JsonGenerationException e) {
             logger.error(e.getMessage(), e);
          } catch (JsonMappingException e) {
             logger.error(e.getMessage(), e);
          } catch (IOException e) {
             logger.error(e.getMessage(), e);
          }
            return null;
        }
    
        /**
         * string --> bean、Map、List(array)
         * 
         * @param jsonStr
         * @param clazz
         * @return obj
         * @throws Exception
         */
        public static <T> T readValue(String jsonStr, Class<T> clazz) {
           try {
             return getInstance().readValue(jsonStr, clazz);
          } catch (JsonParseException e) {
             logger.error(e.getMessage(), e);
          } catch (JsonMappingException e) {
             logger.error(e.getMessage(), e);
          } catch (IOException e) {
             logger.error(e.getMessage(), e);
          }
           return null;
        }
    
       /**
        * string --> List<Bean>...
        *
        * @param jsonStr
        * @param parametrized
        * @param parameterClasses
        * @param <T>
        * @return
        */
       public static <T> T readValue(String jsonStr, Class<?> parametrized, Class<?>... parameterClasses) {
          try {
             JavaType javaType = getInstance().getTypeFactory().constructParametricType(parametrized, parameterClasses);
             return getInstance().readValue(jsonStr, javaType);
          } catch (JsonParseException e) {
             logger.error(e.getMessage(), e);
          } catch (JsonMappingException e) {
             logger.error(e.getMessage(), e);
          } catch (IOException e) {
             logger.error(e.getMessage(), e);
          }
          return null;
       }
    }

    大家可以先看下工具类代码,如果有问题,欢迎沟通交流。有同学会问为什么不用Gson,完全不用考虑这些问题,提前说明下,项目组不让用,至于原因,自行Google...

    之前解析一直都没有问题的,直到有一天程序运行报错,待解析的jsonStr及报错如下

        public static void main(String[] args) {
            String jsonStrErr = "[{\"logId\":1114,\"logDateTim\":1650362257000,\"executeResult\":{\"code\":500,\"msg\":\"block strategy effect\u001ACover Early [job running, killed]\",\"content\":null}},{\"logId\":1115,\"logDateTim\":1650362258000,\"executeResult\":{\"code\":500,\"msg\":\"block strategy effect\u001ACover Early [job running, killed]\",\"content\":null}},{\"logId\":1099,\"logDateTim\":1650362242000,\"executeResult\":{\"code\":500,\"msg\":\"block strategy effect\u001ACover Early [job running, killed]\",\"content\":null}}][{\"logId\":1114,\"logDateTim\":1650362257000,\"executeResult\":{\"code\":500,\"msg\":\"block strategy effect:Cover Early [job running, killed]\",\"content\":null}},{\"logId\":1115,\"logDateTim\":1650362258000,\"executeResult\":{\"code\":500,\"msg\":\"block strategy effect:Cover Early [job running, killed]\",\"content\":null}},{\"logId\":1099,\"logDateTim\":1650362242000,\"executeResult\":{\"code\":500,\"msg\":\"block strategy effect:Cover Early [job running, killed]\",\"content\":null}}]";
            System.out.println(JSONObject.toJSONString(readValue(jsonStrErr, List.class, HandleCallbackParam.class)));
        }
    15:15:13.305 admin [main] ERROR c.w.d.a.c.u.JacksonUtil - Illegal unquoted character ((CTRL-CHAR, code 26)): has to be escaped using backslash to be included in string value
     at [Source: (String)"[{"logId":1114,"logDateTim":1650362257000,"executeResult":{"code":500,"msg":"block strategy effectCover Early [job running, killed]","content":null}},{"logId":1115,"logDateTim":1650362258000,"executeResult":{"code":500,"msg":"block strategy effectCover Early [job running, killed]","content":null}},{"logId":1099,"logDateTim":1650362242000,"executeResult":{"code":500,"msg":"block strategy effectCover Early [job running, killed]","content":null}}][{"logId":1114,"logDateTim":1650362257000,"execut"[truncated 402 chars]; line: 1, column: 77] (through reference chain: java.util.ArrayList[0]->com.wugui.datatx.core.biz.model.HandleCallbackParam["executeResult"]->com.wugui.datatx.core.biz.model.ReturnT["msg"])
    com.fasterxml.jackson.databind.JsonMappingException: Illegal unquoted character ((CTRL-CHAR, code 26)): has to be escaped using backslash to be included in string value
     at [Source: (String)"[{"logId":1114,"logDateTim":1650362257000,"executeResult":{"code":500,"msg":"block strategy effectCover Early [job running, killed]","content":null}},{"logId":1115,"logDateTim":1650362258000,"executeResult":{"code":500,"msg":"block strategy effectCover Early [job running, killed]","content":null}},{"logId":1099,"logDateTim":1650362242000,"executeResult":{"code":500,"msg":"block strategy effectCover Early [job running, killed]","content":null}}][{"logId":1114,"logDateTim":1650362257000,"execut"[truncated 402 chars]; line: 1, column: 77] (through reference chain: java.util.ArrayList[0]->com.wugui.datatx.core.biz.model.HandleCallbackParam["executeResult"]->com.wugui.datatx.core.biz.model.ReturnT["msg"])
        at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:394)
        at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:353)
        at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1711)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:290)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
        at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
        at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:286)
        at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
        at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
        at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3042)
        at com.wugui.datax.admin.core.util.JacksonUtil.readValue(JacksonUtil.java:86)
        at com.wugui.datax.admin.core.util.JacksonUtil.main(JacksonUtil.java:99)
    Caused by: com.fasterxml.jackson.core.JsonParseException: Illegal unquoted character ((CTRL-CHAR, code 26)): has to be escaped using backslash to be included in string value
     at [Source: (String)"[{"logId":1114,"logDateTim":1650362257000,"executeResult":{"code":500,"msg":"block strategy effectCover Early [job running, killed]","content":null}},{"logId":1115,"logDateTim":1650362258000,"executeResult":{"code":500,"msg":"block strategy effectCover Early [job running, killed]","content":null}},{"logId":1099,"logDateTim":1650362242000,"executeResult":{"code":500,"msg":"block strategy effectCover Early [job running, killed]","content":null}}][{"logId":1114,"logDateTim":1650362257000,"execut"[truncated 402 chars]; line: 1, column: 100]
        at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1804)
        at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:693)
        at com.fasterxml.jackson.core.base.ParserMinimalBase._throwUnquotedSpace(ParserMinimalBase.java:657)
        at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._finishString2(ReaderBasedJsonParser.java:2053)
        at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._finishString(ReaderBasedJsonParser.java:2024)
        at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.getText(ReaderBasedJsonParser.java:278)
        at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:35)
        at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:10)
        at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
        ... 11 common frames omitted

    错误内容如标题所示:“Illegal unquoted character ((CTRL-CHAR, code 26))”,意思很明显--非法无引号字符,也就是说jsonStr内部有非法字符集,可这块内容是接口回调返回的,网上有人说是因为不是标准的utf8格式导致的,controler设置一下就可以,但无法解决问题。

    想了一下最简单的方案就是在使用工具类时将非法符号转换一下,将字符转换成““或者和其它格式,仔细查询jsonStr,发现非法的字符应该是“:”,于是很自然就想到最简单地处理方案

        public static void main(String[] args) {
            String jsonStrErr = "[{\"logId\":1114,\"logDateTim\":1650362257000,\"executeResult\":{\"code\":500,\"msg\":\"block strategy effect\u001ACover Early [job running, killed]\",\"content\":null}},{\"logId\":1115,\"logDateTim\":1650362258000,\"executeResult\":{\"code\":500,\"msg\":\"block strategy effect\u001ACover Early [job running, killed]\",\"content\":null}},{\"logId\":1099,\"logDateTim\":1650362242000,\"executeResult\":{\"code\":500,\"msg\":\"block strategy effect\u001ACover Early [job running, killed]\",\"content\":null}}][{\"logId\":1114,\"logDateTim\":1650362257000,\"executeResult\":{\"code\":500,\"msg\":\"block strategy effect:Cover Early [job running, killed]\",\"content\":null}},{\"logId\":1115,\"logDateTim\":1650362258000,\"executeResult\":{\"code\":500,\"msg\":\"block strategy effect:Cover Early [job running, killed]\",\"content\":null}},{\"logId\":1099,\"logDateTim\":1650362242000,\"executeResult\":{\"code\":500,\"msg\":\"block strategy effect:Cover Early [job running, killed]\",\"content\":null}}]";
            System.out.println(JSONObject.toJSONString(readValue(jsonStrErr.replace( new String(Character.toChars(26) ),":"), List.class, HandleCallbackParam.class)));
        }

    如上所写,将jsonStr内非法字符进行转换,语法很简单

    str.replace( new String(Character.toChars(x) ),"")

    这里面的X就是错误里面的(CTRL-CHAR, code 26)对应的code 值,我这里就是26,可以根据实际情况进行修改。简单的处理一下后,工具类运行正常,且能正确的奖str装换成对象。

    但是觉得这种方案过于死板,无法涵盖处理各种可能存在的错误字符,于是在跟回调方确认改非法字符与业务无关后,又想到另一个方案

    private final static ObjectMapper OBJ_MAPPER = new ObjectMapper();
        public static ObjectMapper getInstance() {
            OBJ_MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
            return OBJ_MAPPER;
        }

    意思就很明显了,就是对objectMapper进行配置,允许非法字符。这种方案处理就更方便了,但是仍旧存在问题,比如如特殊字符为key-value中的“:”,且业务中需要对其进行解析,后续的解析逻辑就会报错,所以各位可以根据实际的业务进行处理。

  • 相关阅读:
    一些常用的库[转载]
    《三国演义》很给力演绎60条职场真理
    保证你现在和未来不失业的10种关键技【转载】
    百度面试题
    百度的一到算法i题
    FindMaxDeep
    csinglelink
    FindLongArray
    byte转hex,hex转byte
    获取异常信息
  • 原文地址:https://www.cnblogs.com/JackpotHan/p/16170115.html
Copyright © 2020-2023  润新知