Jackson工具類解析異常--Illegal unquoted character ((CTRL-CHAR, 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中的“:”,且業務中需要對其進行解析,后續的解析邏輯就會報錯,所以各位可以根據實際的業務進行處理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM