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)