Parsing "relaxed" JSON without eval
Solution 1:
You could sanitize the JSON using a regular expression replace:
var badJson = "{muh: 2}";
var correctJson = badJson.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": ');
JSON.parse(correctJson);
Solution 2:
You already know this, since you referred me here, but I figure it might be good to document it here:
I'd long had the same desire to be able to write "relaxed" JSON that was still valid JS, so I took Douglas Crockford's eval-free json_parse.js and extended it to support ES5 features:
https://github.com/aseemk/json5
This module is available on npm and can be used as a drop-in replacement for the native JSON.parse()
method. (Its stringify()
outputs regular JSON.)
Hope this helps!
Solution 3:
This is what I ended up having to do. I extended @ArnaudWeil's answer and added support for having :
appear in the values:
var badJSON = '{one : "1:1", two : { three: \'3:3\' }}';
var fixedJSON = badJSON
// Replace ":" with "@colon@" if it's between double-quotes
.replace(/:\s*"([^"]*)"/g, function(match, p1) {
return ': "' + p1.replace(/:/g, '@colon@') + '"';
})
// Replace ":" with "@colon@" if it's between single-quotes
.replace(/:\s*'([^']*)'/g, function(match, p1) {
return ': "' + p1.replace(/:/g, '@colon@') + '"';
})
// Add double-quotes around any tokens before the remaining ":"
.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?\s*:/g, '"$2": ')
// Turn "@colon@" back into ":"
.replace(/@colon@/g, ':')
;
console.log('Before: ' + badJSON);
console.log('After: ' + fixedJSON);
console.log(JSON.parse(fixedJSON));
It produces this output:
Before: {one : "1:1", two : { three: '3:3' }}
After: {"one": "1:1", "two": { "three": "3:3" }}
{
"one": "1:1",
"two": {
"three": "3:3"
}
}
Solution 4:
JSON5 looks pretty well-supported, but this relaxed-json library also looks like a good option.
Solution 5:
If you can't quote keys when writing the string, you can insert quotes before using JSON.parse-
var s= "{muh: 2,mah:3,moh:4}";
s= s.replace(/([a-z][^:]*)(?=\s*:)/g, '"$1"');
var o= JSON.parse(s);
/* returned value:[object Object] */
JSON.stringify(o)
/* returned value: (String){
"muh":2, "mah":3, "moh":4
}