Are there any forbidden characters in key names, for JavaScript objects or JSON strings? Or characters that need to be escaped?
To be more specific, I'd like to use "$", "-" and space in key names.
No. Any valid string is a valid key. It can even have " as long as you escape it:
{"The \"meaning\" of life":42}
There is perhaps a chance you'll encounter difficulties loading such values into some languages, which try to associate keys with object field names. I don't know of any such cases, however.
The following characters must be escaped in JSON data to avoid any problems:
" (double quote)
\ (backslash)
all control characters like \n, \t
JSON Parser can help you to deal with JSON.
It is worth mentioning that while starting the keys with numbers is valid, it could cause some unintended issues.
Example:
var testObject = {
"1tile": "test value"
};
console.log(testObject.1tile); // fails, invalid syntax
console.log(testObject["1tile"]; // workaround
Unicode codepoints U+D800 to U+DFFF must be avoided: they are invalid in Unicode because they are reserved for UTF-16 surrogate pairs. Some JSON encoders/decoders will replace them with U+FFFD. See for example how the Go language and its JSON library deals with them.
So avoid "\uD800" to "\uDFFF" alone (not in surrogate pairs).
Related
What I am trying to do is simple. Parse this array holding json objects into a Javascript array.
var merchantsJson = JSON.parse('[{"id":61693,"name":"Más"},{"id":61690,"name":"\u0027\u0022\u003C/div\u003E"}]');
But the unicode character \u003C seems to be breaking the parser. In the chrome console I see "Uncaught SyntaxError: Unexpected token <"
A little more info. The above is what the code is evaluated to. In reality the code contains a jsp expression.
var merchantsJson = JSON.parse('${jsonArr}');
If I remove the single quotes, there is no issue, but eclipse give me an "missing semicolon" error message. Is it possible to parse the array with the quotes as I am trying to do?
The interpolation of ${jsonArr} is already a JavaScript object. When you wrap it in '${jsonArr}' this turns it into a string and you have to use JSON.parse.
There's no need to make it a string. You can just do var merchantsArray = ${jsonArr}. JSON constructs are already interoperable with JavaScript code.
Because there's an extra " in your string literal that is encoded by \u0022:
> '[{"id":61693,"name":"Más"},{"id":61690,"name":"\u0027\u0022\u003C/div\u003E"}]'
[{"id":61693,"name":"Más"},{"id":61690,"name":"'"</div>"}]
In short, your JSON in the string is invalid. You would need to escape the unicode escape sequences for the quotes in the string literal ("'\u0022</div>"), by using
JSON.parse('[{"id":61693,"name":"Más"},{"id":61690,"name":"\u0027\\u0022\u003C/div\u003E"}]'
// ^
or escape the quote character ("'\"</div>"):
JSON.parse('[{"id":61693,"name":"Más"},{"id":61690,"name":"\u0027\\\u0022\u003C/div\u003E"}]');
// ^^
However, there actually is no need to use JSON at all. Just output a JS array literal into your code:
var merchantsJson = ${jsonArr};
Try to replace \u with \\u. If you don't, JSON parser receives already decoded Unicode, which created polluted JSON.
It's not because of \u003C, rather the \u0022 character is causing the issue, since it's a quotation mark and JavaScript treats it literally ending the string.
You need to escape that character: \\u0022 .
you have to use special character in your JSON string, you can escape it using \ character.
you need to replace \ with \\.
[{\"id\":61693,\"name\":\"Más\"},{\"id\":61690,\"name\":\"\\u0027\\u0022\\u003C/div\\u003E\"}]
var jsn=getAttr(ref,"json-data").toString();
console.log(jsn); //{test: true,stringtest:"hallo"}. it's OK.
JSON.parse(jsn); //Uncaught SyntaxError: Unexpected token s, line: line with JSON.parse;
I think JSON.parse does something not right with this data.. I tried to remove stringtest:"hallo" - no result... PS: also I think that I do something wrong then I have asked this question
At the first time I tried JSON.parse("{"+jsn+"}");.
Your JSON is not properly formatted, as your object keys must be surrounded by quotation marks. The following will work:
var jsn = '{"test": true, "stringtest": "hallo"}';
JSON.parse(jsn);
Edit: The RFC4627, which specifies JSON format, states:
2.2. Objects
An object structure is represented as a pair of curly brackets
surrounding zero or more name/value pairs (or members). A name is a
string. A single colon comes after each name, separating the name
from the value. A single comma separates a value from a following
name. The names within an object SHOULD be unique.
object = begin-object [ member *( value-separator member ) ]
end-object
member = string name-separator value
As you can see, JSON objects are composed of name/value pairs, where a name is a string. Again, the RFC says:
The representation of strings is similar to conventions used in the C
family of programming languages. A string begins and ends with
quotation marks. All Unicode characters may be placed within the
quotation marks except for the characters that must be escaped:
quotation mark, reverse solidus, and the control characters (U+0000
through U+001F).
string = quotation-mark *char quotation-mark
quotation-mark = %x22 ; "
So, according to the RFC, keys must be surrounded by double quotes, not single one. Still, I guess some parsers may be more tolerant and accept both of them, but I'd stick to the standard.
Are there any forbidden characters in key names, for JavaScript objects or JSON strings? Or characters that need to be escaped?
To be more specific, I'd like to use "$", "-" and space in key names.
No. Any valid string is a valid key. It can even have " as long as you escape it:
{"The \"meaning\" of life":42}
There is perhaps a chance you'll encounter difficulties loading such values into some languages, which try to associate keys with object field names. I don't know of any such cases, however.
The following characters must be escaped in JSON data to avoid any problems:
" (double quote)
\ (backslash)
all control characters like \n, \t
JSON Parser can help you to deal with JSON.
It is worth mentioning that while starting the keys with numbers is valid, it could cause some unintended issues.
Example:
var testObject = {
"1tile": "test value"
};
console.log(testObject.1tile); // fails, invalid syntax
console.log(testObject["1tile"]; // workaround
Unicode codepoints U+D800 to U+DFFF must be avoided: they are invalid in Unicode because they are reserved for UTF-16 surrogate pairs. Some JSON encoders/decoders will replace them with U+FFFD. See for example how the Go language and its JSON library deals with them.
So avoid "\uD800" to "\uDFFF" alone (not in surrogate pairs).
I'm trying to construct a javascript array from a db query. Each item in the array is a string that can contain many different characters that mess up the array. Single quotes, double quotes, parens, etc...
Here's an example of my current output:
var titleList = new Array('Fallout: New Vegas Teaser-Trailer HD','Saints NFC Champions','Best action scene of all time','NJ Lady ep 5: Our Grandma watches Jersey Shore','Australian Banker Caught Looking At Racy Images Of Model Miranda Kerr On Live Television','LEAKED FOOTAGE: New Griswold's "Vacation" Movie?','"A.D." teaser (ZOMBIE ANIMATION)'
...and so on
Is there a special way i can encapsulate each array item so that the title's characters dont interfere with the JS?
Thanks for your help.
Yes, you can escape these characters. Read about JSON.
Example (Hebrew text in json serialized object):
{"updated_at":"2010/02/01 09:55:15 +0000",
"title":"\u05d5\u05d9\u05ea\u05d5\u05e8"}
In general you need to escape the quoting characters you’re using for the string declaration. So in case of your string, you need to escape the ' inside your string declaration:
'LEAKED FOOTAGE: New Griswold\'s "Vacation" Movie?'
You either have to do the replacement manually (with some string replace function). Or maybe your language does support JSON functions. That would definitely be the better choice.
You can escape some special characters (double quote, single quote, newline, tab,..) with \ e.g.: var foo = "\" is just a double quote"
The JSON spec says that JSON is an object or an array. In the case of an object,
An object structure is represented as a pair of curly brackets
surrounding zero or more name/value pairs (or members). A name is a
string. ...
And later, the spec says that a string is surrounded in quotes.
Why?
Thus,
{"Property1":"Value1","Property2":18}
and not
{Property1:"Value1",Property2:18}
Question 1: why not allow the name in the name/value pairs to be unquoted identifiers?
Question 2: Is there a semantic difference between the two representations above, when evaluated in Javascript?
I leave a quote from a presentation that Douglas Crockford (the creator of the JSON standard) gave to Yahoo.
He talks about how he discovered JSON, and amongst other things why he decided to use quoted keys:
....
That was when we discovered the
unquoted name problem. It turns out
ECMA Script 3 has a whack reserved
word policy. Reserved words must be
quoted in the key position, which is
really a nuisance. When I got around
to formulizing this into a standard, I
didn't want to have to put all of the
reserved words in the standard,
because it would look really stupid.
At the time, I was trying to convince
people: yeah, you can write
applications in JavaScript, it's
actually going to work and it's a good
language. I didn't want to say, then,
at the same time: and look at this
really stupid thing they did! So I
decided, instead, let's just quote the
keys.
That way, we don't have to tell
anybody about how whack it is.
That's why, to this day, keys are quoted in
JSON.
You can find the complete video and transcript here.
Question 1: why not allow the name in the name/value pairs to be unquoted identifiers?
The design philosophy of JSON is "Keep it simple"
"Quote names with "" is a lot simpler than "You may quote names with " or ' but you don't have to, unless they contain certain characters (or combinations of characters that would make it a keyword) and ' or " may need to be quoted depending on what delimiter you selected".
Question 2: Is there a semantic difference between the two representations above, when evaluated in Javascript?
No. In JavaScript they are identical.
Both : and whitespace are permitted in identifiers. Without the quotes, this would cause ambiguity when trying to determine what exactly constitutes the identifier.
In javascript objects can be used like a hash/hashtable with key pairs.
However if your key has characters that javascript could not tokenize as a name, it would fail when trying it access like a property on an object rather than a key.
var test = {};
test["key"] = 1;
test["#my-div"] = "<div> stuff </div>";
// test = { "key": 1, "#my-div": "<div> stuff </div>" };
console.log(test.key); // should be 1
console.log(test["key"]); // should be 1
console.log(test["#my-div"]); // should be "<div> stuff </div>";
console.log(test.#my-div); // would not work.
identifiers can sometimes have characters that can not be evaluated as a token/identifier in javascript, thus its best to put all identifiers in strings for consistency.
If json describes objects, then in practise you get the following
var foo = {};
var bar = 1;
foo["bar"] = "hello";
foo[bar] = "goodbye";
so then,
foo.bar == "hello";
foo[1] == "goodbye" // in setting it used the value of var bar
so even if your examples do produce the same result, their equivalents in "raw code" wouldn't. Maybe that's why?? dunno, just an idea.
I think the right answer to Cheeso's question is that the implementation surpassed the documentation. It no longer requires a string as the key, but rather something else, which can either be a string (ie quoted) or (probably) anything that can be used as a variable name, which I will guess means start with a letter, _, or $, and include only letters, numbers, and the $ and _.
I wanted to simplify the rest for the next person who visits this question with the same idea I did. Here's the meat:
Variable names are not interpolated in JSON when used as an object key (Thanks Friedo!)
Breton, using "identifier" instead of "key", wrote that "if an identifier happens to be a reserved word, it is interpreted as that word rather than as an identifier." This may be true, but I tried it without any trouble:
var a = {do:1,long:2,super:3,abstract:4,var:5,break:6,boolean:7};
a.break
=> 6
About using quotes, Quentin wrote "...but you don't have to, unless [the key] contains certain characters (or combinations of characters that would make it a keyword)"
I found the former part (certain characters) is true, using the # sign (in fact, I think $ and _ are the only characters that don't cause the error):
var a = {a#b:1};
=> Syntax error
var a = {"a#b":1};
a['a#b']
=> 1
but the parenthetical about keywords, as I showed above, isn't true.
What I wanted works because the text between the opening { and the colon, or between the comma and the colon for subsequent properties is used as an unquoted string to make an object key, or, as Friedo put it, a variable name there doesn't get interpolated:
var uid = getUID();
var token = getToken(); // Returns ABC123
var data = {uid:uid,token:token};
data.token
=> ABC123
It may reduce data size if quotes on name are only allowed when necessary