unicode字元串解析

  • 2019 年 10 月 30 日
  • 筆記

現象和答案

在http介面接收時,很多介面提供方都喜歡把漢字通過unicode的方式傳過來,而數字和字母保持不變,就像這樣。

{「Content」:"[reply]CocoWu892[/reply]nu6c9fu901au662fu6700u91cdu8981u7684u6280u80fdu4e4bu4e00"}

這裡就必須涉及到一個帶unicode字元串轉成正常字元串的過程。網上關於這塊問題有很多部落格,大部分都是一樣的,實現思路是在字元串中找到n[0-9]{4}字元串,並將匹配到的四位數字通過Integer.parseInt()來轉成字元串。我認為一定有開源jar完成了這個工作,我們應該不用自造輪子。經過尋找,發現fastjson能自動的轉換unicode字元串。

fastjson,已經實現unicode字元串解析,JSON.parseObject(String)等方法都可以。

實現原理,fastjson實現過程,自造輪子

接下來內容是具體實現,實現方式原理和fastjson的實現方式。

我們先了解一下unicode碼,unicode碼u8981u是標示,告訴你這是一個unicode碼,8981是碼的內容,是16位數字,根據8981在unicode碼庫中找到對應字元。在string中的字元實際是\8981可以通過(char)Integer.parseInt("8981",16)來轉碼。

在fastjson中,unicode的解析在JSONLexerBase.scanString()。fastjson字元串(遍歷),發現當前字元是"時,便執行該方法。scanString()方法內容如下,遍歷之後的字元,如果是,跳出循環;如果是\進入特殊字元解析,比如",n,u之類,如果是u便開始unicode解析。

ch = next();  switch (ch) {    case ...      case 'u':      char u1 = ch = next();      char u2 = ch = next();      char u3 = ch = next();      char u4 = ch = next();      int val = Integer.parseInt(new String(new char[] { u1, u2, u3, u4 }), 16);      putChar((char) val);      break;  }

如果僅僅做一個unicode解析,可以使用正則進行匹配和替換,這是自造輪子,仿的String.replaceAll();

    public String parseString(String content) {          String unicodeRegix = "\\u(.{4})";          Pattern pattern = Pattern.compile(unicodeRegix);          Matcher matcher = pattern.matcher(content);          StringBuffer sb = new StringBuffer();          while (matcher.find()) {              String result = matcher.group(1);              int val = Integer.valueOf(result,16);              matcher.appendReplacement(sb, "" + (char) val);          }          matcher.appendTail(sb);          return sb.toString();      }

調用和結果

    @Test      public void parseString() {          UnicodeUtil unicodeUtil = new UnicodeUtil();          System.out.println(unicodeUtil.parseString("{"Content":"[reply]CocoWu892[\/reply]\n\u6c9f\u901a\u662f" +                  "\u6700\u91cd\u8981\u7684\u6280\u80fd\u4e4b\u4e00"}"));      }

Connected to the target VM, address: 『127.0.0.1:60255』, transport: 『socket』 {「Content」:"[reply]CocoWu892[/reply]n溝通是最重要的技能之一"}