JSON.parse() returning strings - javascript

I am trying to iterate through an array of objects and populate an HTML select element with options whose values are the entire contents of each object. The population is successful, but the objects are turned into strings in the process and I do not know how to turn them back into objects.
Running them through JSON.parse() gives me "Uncaught SyntaxError: Unexpected token o in JSON at position 1 at JSON.parse." My research suggests that this happens when you use JSON.parse() on something that is already an object, but running typeOf() on the data beforehand reveals that it is a string.
I do not get this error if I instead run the data through JSON.parse(JSON.stringify(data)), but its output remains a string.
Please help me understand what I am misapprehending about JSON.parse(). Thank you.
const selectors = document.getElementsByClassName("ingredientSelector");
const cookButton = document.getElementById("cookButton");
//very large array of ingredient objects
let selectorOptions = "<option value = 'Nothing'>Nothing</option>";
for (let i = 0; i < ingredients.length; i++){
selectorOptions += ("<option value = '" + ingredients[i] + "'>" + ingredients[i].name + "</option>");
}
Array.prototype.forEach.call(selectors,function(selector){
selector.innerHTML = selectorOptions;
});
function cook(ingredients){
console.log("Cooking with ingredients: " + ingredients);
}
cookButton.addEventListener("click", function(){
let ingredients = [];
Array.prototype.forEach.call(selectors,function(selector){
if(selector.value !== 'Nothing'){
console.log(typeof(selector.value))
JSON.parse(selector.value);
let JSONString = JSON.stringify(selector.value);
console.log(typeof(JSONString));
let JSONObject = (JSON.parse(JSONString));
console.log(typeof(JSONObject));
console.log(JSONObject.name);
}
console.log(ingredients);
cook(ingredients);
});
});

The issue is how you're building the value properties for the options you're inserting into each selector. On this line:
selectorOptions += ("<option value = '" + ingredients[i] + "'>" + ingredients[i].name + "</option>");
Your comment says that ingredients is an array of objects, so ingredients[i] will be an object. Concatenating an object to a string will, by default, turn it into [object Object] - and this is what's causing your error. You're ending up with an option that looks something like this, perhaps:
<option value = '[object Object]'>Raw Prime Meat<object>
There's two perfectly valid approaches here. You can either store the ingredient index in the option values, which you can then use to lookup the ingredient from your master array later, or you should use JSON.stringify(ingredients[i]) to turn the object into a JSON.parseable string to make your code work as-is.
So this would work fine:
selectorOptions += ("<option value = '" + JSON.stringify(ingredients[i]) + "'>" + ingredients[i].name + "</option>");

Related

if array exists in Obj, get array item, if not just get field

works correctly when nested obj arrays are found; however if not found becomes null and breaks page. How could I simply check if exists before hand, and if not just output next level field?
Below works when both arrays are present in relational data objs - however sometimes .NextObj does not contain an array but rather just field - in this case it should probably just be called like .NextObj.field as opposed to .NextObj[0].field which works when array is found. How do you handle both possibilities?
html += "<li class='information'>" + item.OutterObj[0].NextObj[0].url + "</li>";
Update; with the below suggestion it is still throwing when the first item.OutterObj[0] is found null.
TypeError: Cannot read property '0' of null
Have you tried check if it exists first?. Something like this.
field = item.OutterObj[0].NextObj[0] ? item.OutterObj[0].NextObj[0].field : item.OutterObj[0].NextObj.field;
html += "<li class='information'>" + field + "</li>";
Update
For a more generic solution you can use.
field = getProperty(item, ['OutterObj','NextObj', 'url']);
html += "<li class='information'>" + field + "</li>";
function getProperty(rootObject, properties){
properties.forEach(function(property){
rootObject = rootObject[0] ? rootObject[0][property] : rootObject[property]
});
return rootObject;
}

JavaScript get Objects property

Hello guys I've web page which have a lot of scripts, I need to get one by it's name. for e.g 'data'. I need to convert data from this script to one string.
Script is the following:
<script>data = [{'Id': '12344567', 'name': 'TestName','Amount': '1066.00', 'NumberTax': '34.00','tranasactionNumber':'139', 'otherInfo': [{'sku': 'ET|Adult','name': 'Test','category': 'Normal','price': '1032.0', 'quantity':'3'}]}];</script>
This data has array with some elements and another array inside.
Using my script I can only get info and create string with String elements from my data, but how can I get elements from inner array?
var json = '[{';
for (var i in data[0]) {
console.log('type of data[0][i] = ' + typeof data[0][i]);
if (typeof data[0][i] === 'string') {
json = json + '\'' + i + '\'' + ': ' + '\'' + data[0][i] + '\', ';
console.log(i);
console.log(data[0][i])
} else {
//Get infro from inner array
}
}
json = json + '}]';
console.log(json);
Try JSON.stringify(data) to convert object to string instead of your function.
To access the object inside the array you can use the following code:
var obj = data[0]['otherInfo'][0];
You can then use the same code you have above to loop over it and append its elements. If I understand correctly that if what you wish to do.

Javascript Multidimensional Array is Empty

I think Im misunderstanding something here - I normally work in PHP and think I'm missing something small. My final array tmp is empty and displays as ",,,,,,,,,,,,,,,,". It seems to me my tmp array might be emptied somewhere or the scope gets reset for some reason. I'm using this as coordinates from a table where you can select table rows and posting to a webservice but my array seem to be erroneous.
var length = $("#arrayCount").html();
var letters = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
var col = getSelectedColumn(); //for example sake lets say "B" is the selected column
var row = getSelectedRow(); //selected rows will be from "11" - "16"
var columnIndexStart = letters.indexOf(col[0]);
var tmp = [];
for(var i = row[0]; i <= row[1]; i++) //rows[0] = 11 and rows[1] = 16
{
tmp[i] = [];
for(var j = columnIndexStart; j < letters.length; j++) //columns and starts at index 1 if we work with "B"
{
var val = $("#" + i + "_" + letters[j]).html(); //using the row and letters as the associated DOM elements ID. Easier to retrieve it's HTML then.
if(val != undefined)
{
console.log("Index [" + i + "]['" + letters[j] + "'] = " + val); //works perfectly and prints as it should.
tmp[i]['"'+letters[j]+'"'] = val; //using quotes to save letters? Is this preferred?
}
}
}
console.log('Final Array: ' + tmp); //empty??
console.log('Final Array: ' + tmp[14]['G']); //testing HTML output. But is undefined.
return tmp;
Any help will be greatly appreciated.
Edited:
Example of console output.
My final array tmp is empty and displays as ",,,,,,,,,,,,,,,,"
With non-numeric index you are setting the field of object and not the element for index.
If you will have two-dimensional numeric array with numeric indices like the following:
var tmp = [[1,2,3], [1,2,3]];
after console.log('tmp = ' + tmp); you will obviously get the output string like:
tmp = 1,2,3,1,2,3
Because when you are trying to convert array to string it converts it elements to string and represent them with a commas.
However when you are trying to set element with non-numeric index, you are setting the field of this object.
var tmp = [];
tmp['A'] = 123;
console.log("tmp = " + tmp); // tmp =
console.log(tmp.A); //123
So, console.log in your case works good - it is serializing all elements of two-dimensional array. But no one array of the second level does not have stored values, it has only fields, which are not included in the string representation of array.
You are getting a set of commas, because each sub-array of tmp array does not contains any element, so it's string representation is an empty string. Each sub-array contains the required data into it's fields.
When you are performing sum operation of string and object you are forcing object to convert to string representation. Instead of this it is recommended to use console.log(yourObj) - it will log the whole object without converting it to string.
//using quotes to save letters? Is this preferred?
No, "A" and A are different identifiers.
var s = new Object();
s['"A"'] = 123;
console.log(s['A']); //undefined
console.log(s['"A"']); //123
Additionally, if you will set fields with quotes - you can not get the field in normal style:
console.log(s."A"); //syntax error : expected identifier after '.'
You can also just do this (use comma, not plus):
console.log('Final Array: ', tmp); //empty??
console.log('Final Array: ', tmp[14]['G']);

Javascript getting object properties

I want to create a google.Visualization.DataTablein the end, to show a graph. By now, I have a Problem with the following:
This is my code for getting Object from JSON-string and listing Properties:
var jsonData = <?php echo "'". $jsonTable. "'"; ?>;
var parsed = JSON.parse(jsonData);
var sensors = [];
for (var x in parsed){
sensors.push(parsed[x]);
}
var text ="";
for (var sensor in sensors){
if (sensors.hasOwnProperty(sensor)){
var measures = sensors[sensor];
text += ('\r\n' + sensor);
for (var time in measures){
if(measures.hasOwnProperty(time)){
text += ('\r\n' + time + " = " + measures[time]);
}
}
}
}
$(document.getElementById('chart_div')).text(text);
And my jsonData looks like this:
jsonData = '{"sensor1":
{"Date(2016,1,08,10,30,03)":19.187,
"Date(2016,1,08,10,00,02)":18.937[,...]},
"sensor2":
{"Date(2016,1,08,10,30,04)":18.687,
"Date(2016,1,08,10,00,03)":18.437[,...]}
[,...]}'
My Problem is that i don't get the values "sensor1", "sensor2" and so on in the loop. text += ('\r\n' + sensor); only returns the index of the sensor-object in the sensors-object.
How can I get the sensor name instead of the index?
One simple workaround
Remove the var sensors = [];
Find sensors and replace with parsed.
Code:
for (var sensor in parsed){
if (parsed.hasOwnProperty(sensor)){
var measures = parsed[sensor];
text += ('\r\n' + sensor);
console.log(parsed);
for (var time in measures){
if(measures.hasOwnProperty(time)){
text += ('\r\n' + time + " = " + measures[time]);
}
}
}
How can I get the sensor name instead of the index?
You need to do something with the property name in your first loop.
At present you are taking the property name (sensor1), using it to get the value ({"Date...) and then putting the value in an array while discarding the property name.
The simplest option would be to get rid of your first loop entirely and work with parsed instead of sensors in your second loop.

JSON to HTML using JSON.parse undefined error

When trying to parse the JSON
[{"title":"First Item","href":"first","children":[{"title":"Sub First Item","href":"sub"}]},{"title":"Second Item","href":"home"}]
into a list for navigation its just returning undefined.
I was using code from another answer which was working fine with hardcoded JSON but when using it from a textbox (as its going to be generated using jquery.nestable.js) it just gived undefined and i cant see why, ive tried escaping the quotation marks too but no luck there.
function convertNav(){
var data = document.getElementById('jsonNav').value;
var jsn = JSON.parse(document.getElementById('jsonNav').value);
var parseJsonAsHTMLTree = function(jsn){
var result = '';
if(jsn.title && jsn.children){
result += '<li>' + jsn.title + '<ul>';
for(var i in jsn.children) {
result += parseJsonAsHTMLTree(jsn.children[i]);
}
result += '</ul></li>';
}
else {
result += '<li>' + jsn.title + '</li>';
}
return result + '';
}
var result = '<ul>'+parseJsonAsHTMLTree(jsn)+'</ul>';
document.getElementById('convertedNav').value = result;
}
Ive put it in a jsfiddle
http://jsfiddle.net/nfdz1jnx/
Your code handles only a single Javascript object but, according to your code, all nodes and sub-nodes are wrapped inside Javascript arrays. You can use Array.prototype.forEach to handle the array objects.
Sample code follows.
function convertNav() {
var data = document.getElementById('seriaNav').value;
var jsn = JSON.parse(document.getElementById('seriaNav').value);
var parseJsonAsHTMLTree = function(jsn) {
var result = '';
jsn.forEach(function(item) {
if (item.title && item.children) {
result += '<li>' + item.title + '<ul>';
result += parseJsonAsHTMLTree(item.children);
result += '</ul></li>';
} else {
result += '<li>' + item.title + '</li>';
}
});
return result + '';
};
var result = '<ul>' + parseJsonAsHTMLTree(jsn) + '</ul>';
document.getElementById('convertedNav').value = result;
}
<textarea class="span7" style="width:400px;height:100px;" id="seriaNav">[{"title":"First Item","href":"first","children":[{"title":"Sub First Item","href":"sub"}]},{"title":"Second Item","href":"home"}]</textarea>
<hr />
<button class="btn btn-primary" onClick="convertNav();return false;">Convert</button>
<hr />
<textarea class="span5" style="width:400px;height:100px;" id="convertedNav"></textarea>
Your jsn variable is an array. You're getting a list of Objects back and you'll need to parse each one.
Add this after you get jsn back and you'll see an example of retrieving your data.
alert(jsn[0].title);
Your JSON is parsed into an array of objects. With this in mind, your paths to extract information are wrong. For example, you have:
if(jsn.title...
...whereas there is no jsn.title. There is, however, json[0].title.
Basically, you're missing a loop, over the objects. After
var result = '';
add
for (var i=0, len=jsn.length; i
...and in code subsequent to that change all references to jsn to jsn[i]
And of course close the loop further down.
(Finally, at the risk of being pedantic, jsn is not the best name for the var; it's not JSON anymore; it used to be, but now it's parsed, so it's an array. JSON is a string.)
[{"title":"First Item","href":"first","children":[{"title":"Sub First Item","href":"sub"}]},{"title":"Second Item","href":"home"}]
This is not JSON, this is an array of objects. You don't need to parse this. It's already parsed. It's a javascript object.
You should be able to just parse it like you would a regular object.
data[0].title
data[0].children[1].title
etc.

Categories