JS/Nodejs can't access quoted index of object - javascript

I use babyparse (PapaParse) in nodejs to process csv to javascript objects.
One object output is as follows:
{ 'ProductName': 'Nike t-shirt',
ProductPrice: '14.99',
ProductPriceOld: '39.99' }
You can see that somehow the first index is quoted ('ProductName').
I can't manage to access this value. I have tried:
console.log(product['ProductName'])
console.log(product["\'ProductName\'"])
console.log(product['\'ProductName\''])
console.log(product.ProductName)
This all results in 'undefined'. product.ProductPrice or product['ProductPrice'] gives me the correct value.
Any idea what can be causing this, and how to solve it?
Edit: if I JSON.stringify(product) the single quotes are gone, but if I JSON.parse(json) into the object, the single quotes return..?

The reason that the property name is expressed as a string instead of an identifier in the output is that the name includes characters which aren't allowed in an identifier.
Specifically, the first character is: U+FEFF : ZERO WIDTH NO-BREAK SPACE [ZWNBSP] (alias BYTE ORDER MARK [BOM]).
You need to include that in the property name when you access it.
product["\uFEFFProductName"]

Related

Accessing Javascript Object with Key

I have the following object self.originalData on the console:
However, when I try to access to first object in the array of originalData,
self.originalData[0hcMSJXljH]
getting the following error
the Uncaught>Syntax Error: Unexpected token ILLEGAL
I could not able to figure out where I am doing wrong.
You can use:
self.originalData["0hcMSJXljH"]
instead. Object keys are strings so if you use the [] notation, then you have to put a string or a variable that contains a string inside the brackets.
Your particular case is a bit unusual because usually, you can use the dot notation as in obj.property, but because your key starts with a number, it is not a legal identifier to use with the dot notation (you can't do self.originalData.0hcMSJXljH). So, you are forced to use the bracket notation with that particular key.
Try putting the key in quotes like this:
self.originalData['0hcMSJXljH']
You don't use quotes in your key, so it seems you are trying to use the variable identified by 0hcMSJXljH as the key. However, 0hcMSJXljH isn't a valid variable identifier, because it begins with a number, so your get an illegal-character error.
Simply use a string, not an identifier:
self.originalData["0hcMSJXljH"]
Have you tried
self.originalData["0hcMSJXljH"];
?
Otherwise:
self.originalData.0hcMSJXljH;
EDIT: last one not possible because the first char is a number, as explained to me
You must use quotes:
self.originalData['0hcMSJXljH']

What does .split() return if the string has no match?

In this JavaScript code if the variable data does not have that character . then what will split return?
x = data.split('.');
Will it be an array of the original string?
Yes, as per ECMA262 15.5.4.14 String.prototype.split (separator, limit), if the separator is not in the string, it returns a one-element array with the original string in it. The outcome can be inferred from:
Returns an Array object into which substrings of the result of converting this object to a String have been stored. The substrings are determined by searching from left to right for occurrences of separator; these occurrences are not part of any substring in the returned array, but serve to divide up the String value.
If you're not happy inferring that, you can follow the rather voluminous steps at the bottom and you'll see that's what it does.
Testing it, if you type in the code:
alert('paxdiablo'.split('.')[0]);
you'll see that it outputs paxdiablo, the first (and only) array element. Running:
alert('pax.diablo'.split('.')[0]);
alert('pax.diablo'.split('.')[1]);
on the other hand will give you two alerts, one for pax and one for diablo.
.split() will return an array. However,
The value you are splitting needs to be a string.
If the value you are splitting doesn't contain the separator, and the value ends up being an integer (or something other than a string) the call to .split() will throw an error:
Uncaught TypeError: values.split is not a function.
For example, if you are loading in a comma-separated list of ID's, and the record has only has one ID (ex. 42), and you attempt to split that list of ID's, you will get the above error since the value you are splitting is considered an int; not a string.
You may want to preface the value you are splitting with .toString():
aValueToSplit.toString().split('.');

Parsing malformed JSON in JavaScript

Thanks for looking!
BACKGROUND
I am writing some front-end code that consumes a JSON service which is returning malformed JSON. Specifically, the keys are not surrounded with quotes:
{foo: "bar"}
I have NO CONTROL over the service, so I am correcting this like so:
var scrubbedJson = dirtyJson.replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2": ');
This gives me well formed JSON:
{"foo": "bar"}
Problem
However, when I call JSON.parse(scrubbedJson), I still get an error. I suspect it may be because the entire JSON string is surrounded in double quotes but I am not sure.
UPDATE
This has been solved--the above code works fine. I had a rogue single quote in the body of the JSON that was returned. I got that out of there and everything now parses. Thanks.
Any help would be appreciated.
You can avoid using a regexp altogether and still output a JavaScript object from a malformed JSON string (keys without quotes, single quotes, etc), using this simple trick:
var jsonify = (function(div){
return function(json){
div.setAttribute('onclick', 'this.__json__ = ' + json);
div.click();
return div.__json__;
}
})(document.createElement('div'));
// Let's say you had a string like '{ one: 1 }' (malformed, a key without quotes)
// jsonify('{ one: 1 }') will output a good ol' JS object ;)
Here's a demo: http://codepen.io/csuwldcat/pen/dfzsu (open your console)
something like this may help to repair the json ..
$str='{foo:"bar"}';
echo preg_replace('/({)([a-zA-Z0-9]+)(:)/','$1"$2"${3}',$str);
Output:
{"foo":"bar"}
EDIT:
var str='{foo:"bar"}';
str.replace(/({)([a-zA-Z0-9]+)(:)/,'$1"$2"$3')
There is a project that takes care of all kinds of invalid cases in JSON https://github.com/freethenation/durable-json-lint
I was trying to solve the same problem using a regEx in Javascript. I have an app written for Node.js to parse incoming JSON, but wanted a "relaxed" version of the parser (see following comments), since it is inconvenient to put quotes around every key (name). Here is my solution:
var objKeysRegex = /({|,)(?:\s*)(?:')?([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*)(?:')?(?:\s*):/g;// look for object names
var newQuotedKeysString = originalString.replace(objKeysRegex, "$1\"$2\":");// all object names should be double quoted
var newObject = JSON.parse(newQuotedKeysString);
Here's a breakdown of the regEx:
({|,) looks for the beginning of the object, a { for flat objects or , for embedded objects.
(?:\s*) finds but does not remember white space
(?:')? finds but does not remember a single quote (to be replaced by a double quote later). There will be either zero or one of these.
([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*) is the name (or key). Starts with any letter, underscore, $, or dot, followed by zero or more alpha-numeric characters or underscores or dashes or dots or $.
the last character : is what delimits the name of the object from the value.
Now we can use replace() with some dressing to get our newly quoted keys:
originalString.replace(objKeysRegex, "$1\"$2\":")
where the $1 is either { or , depending on whether the object was embedded in another object. \" adds a double quote. $2 is the name. \" another double quote. and finally : finishes it off.
Test it out with
{keyOne: "value1", $keyTwo: "value 2", key-3:{key4:18.34}}
output:
{"keyOne": "value1","$keyTwo": "value 2","key-3":{"key4":18.34}}
Some comments:
I have not tested this method for speed, but from what I gather by reading some of these entries is that using a regex is faster than eval()
For my application, I'm limiting the characters that names are allowed to have with ([A-Za-z_$\.][A-Za-z0-9_ \-\.$]*) for my 'relaxed' version JSON parser. If you wanted to allow more characters in names (you can do that and still be valid), you could instead use ([^'":]+) to mean anything other than double or single quotes or a colon. You can have all sorts of stuff in here with this expression, so be careful.
One shortcoming is that this method actually changes the original incoming data (but I think that's what you wanted?). You could program around that to mitigate this issue - depends on your needs and resources available.
Hope this helps.
-John L.
How about?
function fixJson(json) {
var tempString, tempJson, output;
tempString = JSON.stringify(json);
tempJson = JSON.parse(tempString);
output = JSON.stringify(tempJson);
return output;
}

In What Standard is it Made Official That JSON Object Property Names Must Be Double-Quoted?

Checked here:
http://www.json.org/
and here:
http://www.ietf.org/rfc/rfc4627.txt?number=4627
All I'm seeing is that names must be strings, not that they can't use single-quotes. Don't get me wrong, I'm on board with quoted names for JSON. It protects devs from using property names that aren't legit JS variable names and also powerful use of JSON frequently puts traditional values in property-names for things like map-reduction of 2D arrays modeling tables.
I also think it would make sense for all names to consistently use one or the other quote-type in order to avoid assumptions one might make while trying to parse JSON in some language that doesn't have convenient JSON parsing libraries/native-methods coming out of its pores, but I don't see anything in these specs that insists it must be double or single.
All I see in the second link is that they must be strings. Where is it established that they must be double-quoted as a lot of the JSON validators seem to think? Is there another source? If so who own JSON town? I'm feeling like a raggedy-man who lost his way.
From page 4 of the RFC that you link to:
string = quotation-mark *char quotation-mark
...
quotation-mark = %x22 ; "
Property names must be strings, but strings must be delimited with quotation marks (not apostrophes).
See also the diagram of a string on json.org. Note that it starts and ends with " and not branches that would allow ' as an alternative.
Taken from the http://www.json.org site:
Strings are defined as a character sequence enclosed in double quotes.
In the RFC:
string = quotation-mark *char quotation-mark
where
quotation-mark = %x22 ; "

Issue in accessing JSON object?

Am facing issue in accessing the JSON object :
JSON Object am receiving is :
{"71":"Heart XXX","76":"No Heart YYYY"}
I tried to get the value of 71 and 72 separately and use it ...
but am getting some compile time issue as :
Syntax error on token ".71", delete this token
Code:
var map=$("#jsonText").val();
alert(map);
var obj=jQuery.parseJSON(map);
alert("JSON ::"+obj.71);
If am printing obj , am able to view [Object Object]
Can any one out there please help me to find the mistake i did ..I know the question above is asked in many threads in SO . Below are the few threads i found , but failed when i attempted to implement it ..
jquery json parsing
Also tried using the Jquery tutorial given in
Jquery JSON
Its working fine if the key is a String but getting the above error if its a number ...
Try this:
alert("JSON ::" + obj[71]);
"71" isn't a valid property identifier: an identifier should start with a letter, the underscore or the dollar sign. You can avoid this problem using square brackets instead.
Note: everything that's put between square brackets is converted into strings. Even functions, DOM elements or regular expressions: they're all converted with their toString methods, or their superclass' toString.
So 71 there is converted into "71". If you want a little more performance you can directly use the latter. If you don't need it, you can cut some key presses with just 71.
Use instead
alert("JSON ::"+obj["71"]);
according to the rules or javascript a identifier should not start by a number so if it starts by a number or for that matter contains spaces and other special charcters then you should access it by using the [] operator and not by . operator
so obj.71 is invalid but obj["71"] is
try using this site:
http://json.parser.online.fr/

Categories

Resources