当字符串值包含逗号时,JSON.parse在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/这个小提琴将复制该问题,它涉及将数据作为字符串存储在Cookie中并将其重新解析为JSON
但是,因为我已将Cookiefunction作为外部资源( http://www.sam.thinkka.com/clientscripts/cookie_test.js )包含在内,所以您需要确保Safari不会阻止第三方Cookie。
好的,现在我们已经找到了实际问题的根源,我想我可以提供帮助。
问题基本上是你将数据存储到cookie字符串中而不是转义它。 因此,当您设置cookie并且它包含逗号时,逗号可以被视为cookie分隔符。 对于大多数字符串,JSON中的引号似乎掩盖了这种效果(引号也是cookie的相关字符),但是对于这个,它被cookie解析器视为分隔符。
这反过来意味着它被视为cookie的结尾,这意味着当你加载它时,它会被截断。
解决方案:在将其保存为cookie之前转义字符串。 (你的makeCookie()
函数应该这样做)。 您应该能够使用JS escape()
函数。
请参阅cookie规范 ,并注意逗号,双引号,分号等是Cookie的相关字符。
另见: 这个类似的问题
至于为什么它会在Safari而不是其他浏览器中发生……我猜这可能与其他任何东西一样都有运气。 也许其他浏览器的cookie解析器识别出逗号后面的以下字符串无效,从而确定逗号不是分隔符。
您可能还希望看到MDN cookie文章 ,其中包含示例JS coookie库的代码,该库确实执行了所有正确的转义。 您可能需要考虑使用此lib而不是您自己的当前代码。 (或至少部分)
希望有所帮助。
最后,稍微偏离主题,但在使用cookie时需要注意的另一件事:不要忘记,对于您网站上发出的每个http请求,整个cookie字符串都会在两个方向上传输。 因此,如果您有4k的cookie数据,这意味着您网站上的每个html,css,js和图像文件都需要额外的8k带宽。
如果您使用的是大型Cookie,则可以使用其他方法来存储不受此问题影响的本地数据。 本文可能对您有所帮助。
你不需要解析这个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(ad['58658'])
- 匹配递增的类与来自不同循环的递增的id
- 在重复的jQuery / Ajax函数中设置延迟
- body.scrollTop在严格模式下已弃用。 如果处于严格模式,请使用’documentElement.scrollTop’;如果处于怪癖模式,请使用’body.scrollTop’。
- 在javascript中为Array Elements添加Click事件
- 使用drawImage将加载的图像淡入Canvas
- jQuery通过cookie自定义背景
- 如何打开弹出窗口并使用父窗口中的数据填充它?
- 当jQuery .remove()用于删除脚本标记时,它是否清除了加载的javascript?
- 将jQuery的结果用于C#