Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON.parse Fails in Safari when a string value contains a comma

I am building a shopping cart which when a "Buy" button is pressed, a web service returns a JSON output which I then save into a Javascript cookie as a string.

A typical return from the web service might be:

{
   "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
      }       
   }
}

When the return looks like the above, it will fail in Safari ONLY

Having spent a lot of time trying to find some useful mechanism to debug this without buying a Mac, I have finally tracked it down to:

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

The item value has a comma in the string, I save my return value into a cookie with something like:

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

When I try to recall it later:

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

It works fine in EVERY browser, even, apparently, Internet Explorer... EXCEPT Safari

I don't have a Mac so not sure if Safari on Mac is any different, but certainly the Windows version has this error, and so it does on my iPhone and iPad.

The error is:

JSON parse error, unterminated string.

As I say, this appear to be an issue only in Safari, am having difficulty finding a solution though.

Help much appreciated!

EDIT:

I have created a Fiddle: http://jsfiddle.net/jhartnoll/2GLEz/ This Fiddle will replicate the issue, it is relating to storing the data as a string in a Cookie and the re-parsing it to JSON

But, because I have included my Cookie functions as an External Resource (http://www.sam.thinkka.com/clientscripts/cookie_test.js) you will need to ensure that Safari is not blocking third party cookies.

like image 509
Jamie Hartnoll Avatar asked Oct 14 '13 11:10

Jamie Hartnoll


People also ask

Why is JSON parse failing?

The "SyntaxError: JSON. parse: unexpected character" error occurs when passing a value that is not a valid JSON string to the JSON. parse method, e.g. a native JavaScript object. To solve the error, make sure to only pass valid JSON strings to the JSON.

What happens if you JSON parse a string?

Description. JSON.parse() parses a JSON string according to the JSON grammar, then evaluates the string as if it's a JavaScript expression.

When can JSON parse fail?

JSON. parse() parses a string as JSON. This string has to be valid JSON and will throw this error if incorrect syntax was encountered.

How do you handle an apostrophe in JSON?

To use an apostrophe or a single quotation mark (') in a value, add another single quotation mark after the first one. Notice that the value for name in JSONCUSTOMER table is "O''HARA". The name value in JSONCUSTOMER table is saved as O'Hara.


1 Answers

Okay, now we've got to the root of the actual problem, I think I can help.

The problem is basically that you're storing data into the cookie string but not escaping it. So when you set the cookie and it contains commas, the commas can be seen as cookie delimiters. For most of your string, the quotes in the JSON seem to be masking this effect (quotes are also relevant characters for cookies), but for this one it is being seen by the cookie parser as a delimiter.

This in turn means that it is seen as the end of the cookie, which means when you load it back it is truncated at that point.

Solution: Escape the string before saving it as a cookie. (your makeCookie() function should do this). You should be able to use the JS escape() function for this.

See the cookie spec, and note that commas, double quotes, semi-colons, and more are relevant characters for cookies.

See also: this similar issue

As for why it's happening in Safari and not other browsers... I guess that's probably down to luck as much as anything else. Maybe the other browsers' cookie parsers recognise that the following string after the comma isn't valid and thus work out that the comma isn't intended as a delimiter.

You might also want to see the MDN cookie article which includes code for a sample JS coookie library, which does do all the proper escaping. You may want to consider using this lib instead of your own current code. (or at least parts of it)

Hope that helps.

Finally, slightly off topic, but one additional thing to be aware of when using cookies: Don't forget that the entire cookie string is transmitted in both directions for every single http request made on your site. So if you've got 4k of cookie data, that means an additional 8k of bandwidth for every html, css, js and image file on your site.

If you're using large cookies, there are alternative ways to store local data which are not subject to this problem. This article might be helpful for you.

like image 102
Spudley Avatar answered Oct 11 '22 21:10

Spudley