当字符串值包含逗号时,JSON.parse在Safari中失败

时间:2013-10-14 11:36:27

标签: javascript jquery json safari

我正在构建一个购物车,当按下“购买”按钮时,Web服务会返回一个JSON输出,然后我将其作为字符串保存到Javascript cookie中。

来自Web服务的典型回报可能是:

{
   "d":{
      "58658":{
         "id":"58658",
         "qty":"1",
         "singlePrice":"754",
         "salePrice":"754",
         "isBulk":"0",
         "isSor":"0",
         "vatRate":"20.00",
         "masterCat":"6",
         "imgUrl":"http://...img url",
         "singleWeight":"18000",
         "totalAvailableStock":"2",
         "thirdPartyStock":"",
         "item":"Electrovoice Live X Elx115p, Each " // << HERE IS THE ISSUE
      }       
   }
}

当返回如上所示时,它将仅在Safari中失败

花了很多时间试图找到一些有用的机制来调试它而不购买Mac,我终于将其追踪到:

"item":"Electrovoice Live X Elx115p, Each " // << HERE IS THE ISSUE - The comma

item值在字符串中有逗号,我将返回值保存到cookie中,如下所示:

cookies.set('shopping_cart', JSON.stringify(result)); // (where result is the JSON above)

当我稍后再试一次时:

var shopping_cart = cookies.get('shopping_cart');
shopping_cart = JSON.parse(shopping_cart);

它在每个浏览器中都能正常工作,显然,Internet Explorer ......除了Safari

我没有Mac,所以不确定Mac上的Safari是否有任何不同,但Windows版本肯定有这个错误,所以它在我的iPhone和iPad上也是如此。

错误是:

JSON parse error, unterminated string.

正如我所说,这似乎仅在Safari中存在问题,但我很难找到解决方案。

非常感谢!

修改

我创造了一个小提琴:http://jsfiddle.net/jhartnoll/2GLEz/ 这个Fiddle将复制该问题,它涉及将数据作为字符串存储在Cookie中并将其重新解析为JSON

但是,因为我已将Cookie功能作为外部资源(http://www.sam.thinkka.com/clientscripts/cookie_test.js)包含在内,所以您需要确保Safari不会阻止第三方Cookie。

2 个答案:

答案 0 :(得分:10)

好的,现在我们已经找到了实际问题的根源,我想我可以提供帮助。

问题基本上是你将数据存储到cookie字符串中而不是转义它。因此,当您设置cookie并且它包含逗号时,逗号可以被视为cookie分隔符。对于你的大部分字符串,JSON中的引号似乎掩盖了这种效果(引号也是cookie的相关字符),但是对于这个,它被cookie解析器视为分隔符。

这反过来意味着它被视为cookie的结尾,这意味着当你加载它时,它会被截断。

解决方案:在将其保存为cookie之前转义字符串。 (你的makeCookie()函数应该这样做)。您应该可以使用JS escape()函数。

请参阅the cookie spec,并注意逗号,双引号,分号等是Cookie的相关字符。

另请参阅:this similar issue

至于为什么它会在Safari而不是其他浏览器中发生......我想这可能与其他任何东西一样运气。也许其他浏览器的cookie解析器识别出逗号后面的后续字符串无效,从而确定逗号不是分隔符。

您可能还希望看到MDN cookie article,其中包含示例JS coookie库的代码,该库可以执行所有正确的转义。您可能需要考虑使用此lib而不是您自己的当前代码。 (或至少部分内容)

希望有所帮助。

最后,略微偏离主题,但在使用Cookie时需要注意的另一件事:不要忘记,对于您网站上发出的每个http请求,都会在两个方向上传输整个Cookie字符串。因此,如果您有4k的cookie数据,这意味着您网站上的每个html,css,js和图像文件都需要额外的8k带宽。

如果您使用的是大型Cookie,则可以使用其他方法来存储不受此问题影响的本地数据。 This article可能对您有所帮助。

答案 1 :(得分:0)

你不需要解析这个json ...... 尝试:

var a= {
    "d":{
        "58658":{
            "id":"58658",
            "qty":"1",
            "singlePrice":"754",
            "salePrice":"754",
            "isBulk":"0",
            "isSor":"0",
            "vatRate":"20.00",
            "masterCat":"6",
            "imgUrl":"http://...img url",
            "singleWeight":"18000",
            "totalAvailableStock":"2",
            "thirdPartyStock":"",
            "item":"Electrovoice Live X Elx115p, Each " // << HERE IS THE ISSUE
        }
    }
}

console.log(a.d['58658'])