Firefox pref destroys JSON
I have the following JSON: http://pastebin.com/Sh20StJY
SO removed characters in my post, so look at the link for real JSON
which was generated with JSON.stringify
and saved in Firefox prefs ( pref.setCharPref(prefName, value);
)
The problem is that when I store the value, Firefox does something that corrupts the JSON. If I try JSON.parse
to extract the value from the configuration, I get an error:
Error: JSON.parse: bad control character in string literal
If I try to validate the above JSON (which was obtained from settings), I get an error in line 20
, the token value contains two invalid characters.
If I try to execute JSON.parse
right after JSON.stringify
, no error occurs.
Do I need to save something in a different encoding? How can I fix this?
source to share
nsIPrefBranch.getCharPref()
only works for ASCII data, however JSON data contains some non-ASCII characters. You can store Unicode data in preferences, it's a little more complicated:
var str = Components.classes["@mozilla.org/supports-string;1"]
.createInstance(Components.interfaces.nsISupportsString);
str.data = value;
pref.setComplexValue(prefName, Components.interfaces.nsISupportsString, str);
And to read this preference:
var str = pref.getComplexValue(prefName, Components.interfaces.nsISupportsString);
var value = str.data;
For reference: Documentation
source to share
Your JSON appears to contain non-ASCII characters such as ½
. Can you check what encoding everything is processed in?
nsIPrefBranch.setCharPref()
assumes that its input is UTF-8 encoded and the return value is nsIPrefBranch.getCharPref()
always a UTF-8 string. If your input is a byte or character in some other encoding, then you either need to switch to UTF-8 or encode and decode it yourself when interacting with preferences.
source to share
I did this in one place to fix this issue:
(function overrideJsonParse() {
if (!window.JSON || !window.JSON.parse) {
window.setTimeout(overrideJsonParse, 1);
return; //this code has executed before JSON2.js, try again in a moment
}
var oldParse = window.JSON.parse;
window.JSON.parse = function (s) {
var b = "", i, l = s.length, c;
for (i = 0; i < l; ++i) {
c = s[i];
if (c.charCodeAt(0) >= 32) { b += c; }
}
return oldParse(b);
};
}());
This works in IE8 (using json2 or whatever), IE9, Firefox and Chrome.
source to share