舊時代Javascript Escape Unicode字元編碼之探討與解碼

至今還是有人持續在使用舊時代的javascript escape()函式,將Unicode文字進行編碼,然而javascript escape()函式早就因為無法全面進行Unicode的文字編碼而被拋棄了,所以在.NET Framework的伺服器端實作也被拋棄掉了。

但,就是有人偏偏要送這樣的字元給你,怎麼辦?

編碼(Escape、Encode)

javascript施以console.log(escape("測試")),會得到下列的字串:

%u6E2C%u8A66
\u6E2C\u8A66  //而一般來說也會被以這樣的形態表示

在.NET Framework端同樣實作escape的對映方法,稱為System.Web.HttpUtility.UrlEncodeUnicode(),然而隨著escape()函式的黯然退下,這個UrlEncodeUnicode方法也被微軟列為不再支援觀察名單。

System.Web.HttpUtility.UrlEncodeUnicode("測試")
%u6e2c%u8a66  //除了大小寫之外,其他的跟JS escape函式輸出一樣

後來,javascript建議的是使用encodeURIComponent()方法:

encodeURIComponent("測試")
%E6%B8%AC%E8%A9%A6  //不一樣的Unicode文字編碼方式了

對映到.NET Framework自然是System.Web.HttpUtility.UrlEncode()方法:

System.Web.HttpUtility.UrlEncode("測試")
%e6%b8%ac%e8%a9%a6  //除了大小寫之外,其他的跟JS encodeURIComponent函式輸出一樣

解碼(Unescape、Decode)

把這個古老的編碼在伺服器端解譯回來正常的Unicode是很輕鬆的,我們可以使用UrlDecode()方法:

System.Web.HttpUtility.UrlDecode("%u6e2c%u8a66")
測試
System.Web.HttpUtility.UrlDecode("\u6e2c\u8a66")
測試

但這些訊息加上了JSON格式,可就不是那麼的順利了,例如有一個這樣的JSON字串:

{"cMessage":"\u6e2c\u8a66"}

這串JSON丟到UrlEncode裡面是無效的,會傳回一模一樣的字串回來。

如果想要無腦的幫你解決某串JSON中隱含的舊時代javascript escape()編碼文字,其實可以使用.NET Framework的靜態方法System.Text.RegularExpressions.Regex.Unescape(String)來解決,但由於這個方法有可能會把你所有escape的字元都解掉,可能會影響到JSON中不想被解碼的字元,所以請慎用之。

如果你只想專注在解決這個\uXXXX的Unicode字元編碼上的話,可能就只能自己用正規表示式來解決了。

System.Func<string, string> ConvertEscapeChar = x =>
{
  return System.Text.RegularExpressions.Regex.Replace(
    x,
    @"\\[Uu]([0-9A-Fa-f]{4})",
    m => char.ToString(
      (char)ushort.Parse(
        m.Groups[1].Value,
        System.Globalization.NumberStyles.AllowHexSpecifier
      )
    )
  );
};
\uXXXX %uXXXX Javascript Escape Unescape PHP ASP.NET C# Decode Encode