I'm parsing a json object that contains an element named data-config.
ex:
var video = data.element.data-config;
Whenever I parse this element I'm getting this error:
ReferenceError: config is not defined
The ReferenceError doesn't mention data-config but simply config.
Any idea why I'm getting this error?
Is this related with the dash (-) character?
Valid Characters
In general JavaScript, variable/function names can't contain -. They can only contain letters, $, and _ (Underscore)
So...
The error is coming because it's parsing:
var video is equal to data.element.data(valid) minus config
Solution
Because variables can't contain dashes, you need to use what I'm going to call String/Bracket Notation
data.element['data-config']
If you need to do more then one, do
data.element['data-config']['child']
I don't recommend using String/Bracket Notation when you don't have to, it's better practice.
You have to use [] notation when object properties contain special characters
var video = data.element['data-config'];
Related
This question already has answers here:
How to access object property with invalid characters
(2 answers)
Closed 3 years ago.
I'm attempting to access the text value of a JavaScript .json object with under the location of loggie.stats.Wins. Under the Wins column there are 3 subcategories listed: #category, #abbreviation, and #text. I'm particularly interested in the value of #text, but when I attempt:
console.log(JSON.stringify(loggie.stats.Wins.#text))
I receive the error SyntaxError: {app location}\src\App.js: Unknown PrivateName "#text"
I'm assuming there is something about the # and # tags in a json object I do not understand, but I don't know where to look. I can stringify the whole .Wins object and pull it from there I suppose but I'm guessing there is a less convoluted way to go about it.
EDIT: MisterJojo gave me the solution, I needed to access it as loggie.stats.Wins['#text']. I'm hoping he can point me towards a reading source so I can explain in greater detail how the answer works here.
You can't use the dot notation to access JSON fields with names like that.
In your example you probably should do loggie.stats.Wins["#text"] instead.
You can only use the dot notation when your field contains alphanumeric letters only (without space, or special characters with the exception of underscore _), and it must start with an alphabetic character or underscore
e.g.: valid ones:
object.fIelD1234
object.field_name
object._abc
invalid:
object.123abc
object.ab-cd
with special characters you will have to access that field with []
e.g.
object['123abc']
object['ab cd']
object['#123a']
You can't use .#text it is an invalid syntax.
If the Json key is #text, you can access this property like this Wins['#text']
I ran into a problem using the Pipedrive API. I tried to get some data using the below but it returned an error:
$.each(data.data, function(key,value) {
console.log(value.0d1df598a5539ab5b6b410b339dc9218e0acb091);
});
However this works:
$.each(data.data, function(key,value) {
console.log(value.person_name);
});
Why can't I get values of the keys that are complex strings generated by the Pipedrive system?
To retrieve what you require you would need to use bracket notation as the first character of the property identifier is an integer. Try this:
var value = {
'0d1df598a5539ab5b6b410b339dc9218e0acb091': 'foo bar'
}
console.log(value['0d1df598a5539ab5b6b410b339dc9218e0acb091']);
A possible explanation can be summarized in two part
Valid javascript variable(identifier names)
An identifier must start with $, _, or any character in the Unicode categories Uppercase letter (Lu), Lowercase letter, Titlecase letter (Lt), Modifier letter (Lm), Other letter (Lo), or Letter number (Nl).
In your case the identifier name start with an integer(0)
Property accessors
An key of an object in js can be retrieved either by using dot (.) notation or by using Bracket[]` notation
Square brackets notation allows use of characters that cannot be used with dot notation and also to retrieve an identifier which is not valid according to the first point.Beside it also allows to access properties containing special characters.
This is because js interpreter automatically converts the expression within square brackets to a string & retrieves the corresponding value.Actually
js evaluates the first complete expression with square brackets in a statement, runs toString() on it to convert it into a string and then uses that value for the next bracket expression, on down the line till it runs out of bracket expressions.
So dot notation has marginal upper-hand since it wont go throught he above process.
But it cannot be use it with a variable(or number).
It only allow to access explicit key name of a property
Since the identifier in your object identifiers's name starts with an 0 , bracket notation like value['0d1df598a5539ab5b6b410b339dc9218e0acb091'] will give it's value.
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.
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
i have a json string im converting to object with a simple eval(string);
heres the sample of the json string:
var json = #'
"{ description" : { "#cdata-section" : "<some html here>" } }
';
var item = eval('('+json+')');
I am trying to access it like so
item.description.#cdata-section
my problem is that javascript does not like the # in the field name.. is there a way to access it?
item.description['#cdata-section']
Remember that all Javascript objects are just hash tables underneath, so you can always access elements with subscript notation.
Whenever an element name would cause a problem with the dot notation (such as using a variable element name, or one with weird characters, etc.) just use a string instead.
var cdata = item.description["#cdata-section"];
While the official spec for JSON specifies simply for chars to be provided as a field identifier, when you parse your JSON into a Javascript object, you now fall under the restrictions of a Javascript identifier.
In the Javascript spec, an identifier can start with either a letter, underscore or $. Subsequent chars may be any letter, digit, underscore or $.
So basically, the # is valid under the JSON spec but not under Javascript.