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.
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.
Description. JSON.parse() parses a JSON string according to the JSON grammar, then evaluates the string as if it's a JavaScript expression.
JSON. parse() parses a string as JSON. This string has to be valid JSON and will throw this error if incorrect syntax was encountered.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With