【问题标题】:JSON.parse Fails in Safari when a string value contains a comma当字符串值包含逗号时,JSON.parse 在 Safari 中失败
【发布时间】:2013-10-14 11:36:26
【问题描述】:

我正在构建一个购物车,当按下“购买”按钮时,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。

【问题讨论】:

  • 不,逗号不是问题
  • 你能提供一个 jsFiddle 例子来演示这个问题吗?
  • 作为记录,我让你的 JSON 字符串在 Safari 中使用 jsFiddle 工作得很好......见jsfiddle.net/KRR2N 我唯一改变的是删除// &lt;&lt; HERE IS THE ISSUE 评论,因为那是无效的 JSON,但我猜这不在你的原始代码中。
  • @Spudley,谢谢。我也能够让它与那个 Fiddle 一起工作,但是,我已经扩展了 Fiddle 以使用我的 cookies 函数,现在实际上得到了一个不同的错误!建议 Cookie 不起作用,但它们适用于其他所有内容! jsfiddle.net/jhartnoll/2GLEz
  • 好的,我想现在我们有了你的小提琴代码,我们正在解决问题的关键。基本上,它归结为逃避。但请参阅我的答案了解更多信息。

标签: javascript jquery json safari


【解决方案1】:

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

问题基本上是您将数据存储到 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 库的代码,该库确实进行了所有正确的转义。您可能需要考虑使用此库而不是您自己当前的代码。 (或至少部分)

希望对您有所帮助。

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

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

【讨论】:

  • 优秀。谢谢......现在做了两个很好的修改,使用 localStorage 似乎更有意义,我已经修改了我的 Cookies 函数以尽可能使用 localStorage,否则回滚到 Cookies。
  • 在我的 cookie 中添加了逃逸功能
【解决方案2】:

你不需要解析这个 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'])

【讨论】:

  • 我知道我没有,不直接使用它,但如果我想将它保存在 Cookie 中,我会这样做吗?
  • 如果你发布一个小提琴,那就是 gr8
  • 小提琴已发布 - 您必须停止 Safari 阻止第三方脚本才能使小提琴正常工作,但它在这里:jsfiddle.net/jhartnoll/2GLEz
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-26
  • 2020-06-09
  • 2021-12-21
  • 2011-06-11
  • 1970-01-01
  • 2011-10-13
  • 2023-01-31
相关资源
最近更新 更多