2016
Oct
17

JavaScript JSON.parse 不支援斷行,TAB等字元,例如 \n, \r, \t, \b 這些特殊字元,如果你的 json string 有使用到這些字元, JavsScript 就會吐出錯誤訊息,例如下面這個 JS 程式碼,我先宣告一個含有斷行符號的字串 "\n",再用 JSON.parse 將字串轉成 JSON ,這個 sample code 在瀏覽器下執行會出現 error : SyntaxError: Unexpected token 。

Example
  1. <script>
  2. var s = '{"test": "a\nb"}';
  3. var ret = JSON.parse(s);
  4. console.log(ret);
  5. </script>

當然前端很少會直接宣告一個字串,然後又對他做 JSON.parse ,這個問題會發生在後端回傳一個 JSON string ,交給前端做 JSON.parse ,例如 PHP 可能會這樣做:

Example
  1. <?php
  2. $res = array(
  3. "message" => "Got a error,\n error message: unknown",
  4. );
  5.  
  6. echo json_encode($res);
  7. // Output: {"message":"Got a error,\n error message: unknown"

這個範例拿到的 JSON string 含有 "\n",只要 JavaScript 對這個 string 做 JSON.parse 馬上就會中 JS Error。


解決方案

1. 寫 JavaScript 時最好有個習慣,只要用到 JSON.parse 就一定要加上 try catch 機制,我常常遇到特殊字元,造成 JSON.parse fail 的情形,未知的問題比我們想像中的還要多,所以一定要有 parse fail 的處理方式。

2. PHP 對 array 做兩次 json_encode,第二次的 json_encode 會把所有的符號加上跳脫字元,這樣 JavaScript 再做 json parse 時就能夠正確處理斷行,TAB 等符號,要注意,兩次 json_encode 之後所得到的結果會是一個被雙引號括起來的 "string" ,只要先把字串左右兩邊的雙引號移除,JavaScript 只對它做一次 JSON.parse 就能得到 JSON format,不用 JSON.parse 兩次。

Example
  1. <?php
  2. $res = array(
  3. "message" => "Got a error,\n error message: unknown",
  4. );
  5.  
  6. $a = json_encode(json_encode($res));
  7.  
  8. //Output : "{\"message\":\"Got a error,\\n error message: unknown\"}"

3. 第三種解法是手動把有問題的符號加上跳脫字元

Example
  1. <?php
  2. function json_stringify($json) {
  3. if (is_array($json)) $json = json_encode($json);
  4. $search = array('\\', "\n", "\r", "\f", "\t", "\b", "'") ;
  5. $replace = array('\\\\', "\\n", "\\r","\\f","\\t","\\b", "'");
  6. return str_replace($search, $replace, $json);
  7. }
  8.  
  9. $res = array(
  10. "message" => "Got a error,\n error message: unknown",
  11. );
  12. $a = json_stringify($res);
  13. echo <<<HTML
  14. <script>
  15. var s = JSON.parse('$a');
  16. console.log(s);
  17. </script>
  18. HTML;

回應 (Leave a comment)