Extract objects from object in JSON using JavaScript - javascript

So, I have access to a JSON-file and I'm supposed to list a few items in a neat fashion. The JSON-file is however written in a way I'm not familiar with. I have the following code:
function readFile(file) {
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function ()
{
if (rawFile.readyState === 4 && rawFile.status === 200)
{
window.openedFile = JSON.parse(rawFile.responseText);
console.log(JSON.stringify(openedFile, undefined, 4));
createList();
}
};
rawFile.send();
}
function createList() {
var table = document.createElement('table');
var body = document.createElement('tbody');
for (var i = 0; i < openedFile.sites.length; i++) {
var item = document.createElement('tr');
var colSite = document.createElement('td');
colSite.appendChild(document.createTextNode(openedFile.sites[i].name));
item.appendChild(colSite);
body.appendChild(item);
}
table.appendChild(body);
document.getElementById('list').appendChild(table);
}
..and it does not work as it claims the array "sites" is empty. The result from the JSON-file in the output in the console gives (with slight modifications in the variable names):
{
"sites": {
"1007": {
"id": 1007,
"name": "Location B",
"devices": {
"p3": {
"name": "p3",
"version": "5"
}
}
},
"1337": {
"id": 1337,
"name": "Location A",
"devices": {
"p2": {
"name": "p2",
"version": "5"
},
"p1": {
"name": "p1",
"version": "5"
}
}
}
},
}
If I change the JSON-file and add [] brackets after sites and remove "1007" and "1337" it looks like I'm used to (as an ordinary array), and it works. I'm pretty sure I'm not allowed to do this however and I get the same problem again when trying to extract information about the devices. I would appreciate any help on this matter. And to clarify, I'm trying to avoid changing the JSON-file, if there is some other solution.

The numerals 1007 and 1337 are properties of the object sites. Use a for-in loop to iterate through the object properties.
var sites = openedFile.sites;
for(var site in sites){
console.log("Key: ", site);
console.log("Value: ", sites[site]);
}

Sites is an object, not an array, so you need to iterate over the object's properties, not the elements of the array.
In order to get a list of those properties, you can use Object.keys(). That gives you an array of the property names.
Once you have that array, you iterate over it and each time use the current element, which is the name of the property of the original object.
For example, this works (just console logging the object name, the extraction you've already got):
function createList2() {
var len = Object.keys(openedFile.sites); //get array of property keys
for (var i of len) { //iterate over the array of property keys
console.log(openedFile.sites[i].name); /*retrieve properties by key from original object */
}
}

Related

Find elements in json object by number/order in the list

I'm making a help command for a discord bot, right now I'm trying to get a list of all the commands from a json file.
The json file looks like this:
{
"command": {
"help": {
"name": "help",
"syntax": "help str",
"description": "Outputs list of commands or info on a specific command.",
"example": ">>help, >>help gn"
},
"gn": {
"name": "gn",
"syntax": "gn int",
"description": "gn, guess number. Used to guess the secret number, if you get it correct you gain 1 point.",
"example": ">>gn 22"
}
}
}
The code I'm currently trying:
jsonobject = JSON.parse(bufferFile('\command.json'));
if (!input[1]) {
console.log(Object.keys(jsonobject.command).length);
for (var i = 0; i < Object.keys(jsonobject.command).length; i++) {
message.channel.send(jsonobject.command[i].description);
}
}
This should output the description of each command but instead, jsonobject.command[i] is undefined. I tried outputting jsonobject.command and I got [object Object]. Object.keys(jsonobject.command).length does output the correct number of commands.
Where i refers to a number which is used for iteration and it's not the actual key. So keep an array with keys and get key value using index within the loop.
jsonobject = JSON.parse(bufferFile('\command.json'));
if (!input[1]) {
// heys array
var keys = Object.keys(jsonobject.command);
for (var i = 0; i < keys.length; i++) {
message.channel.send(jsonobject.command[keys[i]].description);
// get key from keys array using index --^^^^^----
}
}
With ES6 you can make it simpler using Object.values, Array#forEach, Arrow function and Destructuring assignment.
if (!input[1]) {
Object.values(jsonobject.command).forEach(({description}) => message.channel.send(description))
}
I was beat by seconds by the first answer, which already explains your issue well. Anyway, here's another approach using for ... of (not supported in Internet Explorer, but by all modern browsers).
var jsonobject = {
"command": {
"help": {
"name": "help",
"syntax": "help str",
"description": "Outputs list of commands or info on a specific command.",
"example": ">>help, >>help gn"
},
"gn": {
"name": "gn",
"syntax": "gn int",
"description": "gn, guess number. Used to guess the secret number, if you get it correct you gain 1 point.",
"example": ">>gn 22"
}
}
}
for (var key of Object.keys(jsonobject.command)) {
console.log(key + ': ' + jsonobject.command[key].description);
}

How to prevent default sorting in key value array Javascript

I have this array:
recentPageArray = {
"e49f8a67-3075-433a-bacd-30379008fdb2": {
"id": "e49f8a67-3075-433a-bacd-30379008fdb2",
"name": "afolder",
"type": "indexfolder"
},
"3a1ca419-5467-4662-9f7a-f3e9246a1d49": {
"id": "3a1ca419-5467-4662-9f7a-f3e9246a1d49",
"name": "folder1",
"type": "indexfolder"
},
"832f9d4e-297e-40e9-9189-75ce3b86341a": {
"id": "832f9d4e-297e-40e9-9189-75ce3b86341a",
"name": "afolder",
"type": "documentfolder"
},
"86fee1ce-21cd-4948-bf9d-a6c81b897a0e": {
"id": "86fee1ce-21cd-4948-bf9d-a6c81b897a0e",
"name": "afolder",
"type": "documentfolder"
}
}
Whenever I push new array in the this array. Key sort automatically. I dont want to sort array in the key base. I need new pushed key item in top of the array.
I suggest you to mantain 2 references:
1 Array (list)
1 Object (key, value)
The Object (key->val) cannot mantain the elements' insert order (and if an utopic new browser implementation want to order in descending order(for any cause) your code will be sensible to it).
So, while populating the object,also push the element key in the Array.
When you want to iterate use the Array to iterate in order (and it is also faster)
myObject = {};
myArray = [];
/** POPULATING **/
for (var x in myData){
myObject[myData[x].key] = myData[x].value;
myArray.push(myData[x].key);
}
/** ITERATING **/
for (var y =0; y < myArray.length; y++){
var readingKey = myArray[y];
var storedData = myObject[readingKey];
//your code here
}
Regards

How to not proceed with adding a value if its an empty/null string?

My code reads data somewhere and then adds them as values to properties in an object. I made a for loop to iterate over the items in the list so they can each belong in their own cute little object but here is a problem: sometimes there's no value to a property and I wan't to know what I can do to intercept that before it finishes being declared to the property. Maybe replace the empty string with a word or something.
Here is an example code and lets say the title on iteration #3 is going to be an empty "" string. how do I intercept that?
var counter = 0;
for (var i = 0; i < nyData.results.length; i++) {
if (_.indexOf(uniqueItems, nyData.results[i].id)) {
continue;
}
if (!_.indexOf(uniqueItems, nyData.results[i].id)) {
var index = i;
counter++;
let putParams = {
TableName: "Articles",
Item: {
"title": nyData.results[i].title,
"date": nyData.results[i].published_date,
"abstract": nyData.results[i].abstract,
"source": nyData.results[i].source,
"views": nyData.results[i].views,
"author": nyData.results[i].byline,
"section": nyData.results[i].section,
"category": nyData.results[i].des_facet,
"organizations": nyData.results[i].org_facet,
"people_involved": nyData.results[i].per_facet,
"country_subject": nyData.results[i].geo_facet,
"id": nyData.results[i].id,
}
}
db.put(putParams, function(err) {});
}
}
console.log(`Total of ${counter} new articles were inserted into database.`);
callback(null);
if( myVar) {
}
will only be true, if the variable is not:-
Empty
Null
undefined
0
false
....and a few more.

jQuery object get value by key

How would you get the value of assocIMG by key matching the key eg
if I have a var 11786 I want it to return media/catalog/product/8795139_633.jpg
var spConfig = {
"attributes": {
"125": {
"id": "125",
"code": "pos_colours",
"label": "Colour",
"options": [{
"id": "236",
"label": "Dazzling Blue",
"price": "0",
"oldPrice": "0",
"products": ["11148"]
}, {
"id": "305",
"label": "Vintage Brown",
"price": "0",
"oldPrice": "0",
"products": ["11786", "11787", "11788", "11789", "11790", "11791", "11792", "11793"]
}]
}
}
};
var assocIMG = // Added - Removed { here, causes issues with other scripts when not working with a configurable product.
{
11786: 'media/catalog/product/8795139_633.jpg',
11787: 'media/catalog/product/8795139_633.jpg',
}
Above is the objects I am working with and below is my current jQuery. Help would be greatly appreciated.
$('#attribute125').change(function() {
var image = $(this).val();
$.each(spConfig.attributes, function() {
prods = $(this.options).filter( function() { return this.id == image; } )[0].products[0];
alert(prods);
});
});
You can use bracket notation to get object members by their keys. You have the variable prods containing a string ("11786"), and the object assocIMG with various keys. Then just use
assocIMG[prods]
to get the property value 'media/catalog/product/8795139_633.jpg' which is associated with that key.
Note that you should always use strings as keys in your object literal, IE does not support numbers there:
var assocIMG = {
"11786": 'media/catalog/product/8795139_633.jpg',
"11787": 'media/catalog/product/8795139_633.jpg'
};
Another improvement to your script would be not to loop through the spConfig.attributes each time, and potentially execute your action multiple times if an image is contained in more than one attribute. Instead, build a hash object out of it, where you can just look up the respective product id.
var productById = {};
$.each(spConfig.attributes, function() {
$.each(this.options, function() {
var id = this.id;
productsById[i] = this.products[0];
});
});
$('#attribute').change(function() {
var id = this.value;
var prod = productById[id];
var image = assocIMG[prod];
$("#product_img").attr("src", image);
});
You should not use numbers as object keys (in their start). If you want to get the value associated with the 11786 integer key, you will need to use this syntax:
assocIMG["11786"] or assocIMG[11786]
Not
assocIMG.11786
The first thing that you need to do is to create your keys as strings, since you would have:
var assocIMG = {
"11786": 'media/catalog/product/8795139_633.jpg',
"11787": 'media/catalog/product/8795139_633.jpg',
}
But even doing this, you won't be able to access the field using assocIMG.11786 and the first valid sintax that I presented will still work. The correct approach would be:
var assocIMG = {
id11786: 'media/catalog/product/8795139_633.jpg',
id11787: 'media/catalog/product/8795139_633.jpg',
}
Or
var assocIMG = {
"id11786": 'media/catalog/product/8795139_633.jpg',
"id11787": 'media/catalog/product/8795139_633.jpg',
}
Note that the keys are now starting with letters, not numbers. And now, you will can access the 11786 field as assocIMG.id11786 or assocIMG["id11786"], not assocIMG[id11786]
To Get the Value from object by matching key I ended up with the following
$.each(assocIMG, function(index, value) {
if(index == prods) {
var image_path = value;
$("#product_img").attr("src", image_path);
//alert(image_path);
}

Use a JSON array with objects with javascript

I have a function that will get a JSON array with objects. In the function I will be able to loop through the array, access a property and use that property. Like this:
Variable that I will pass to the function will look like this:
[{
"id": 28,
"Title": "Sweden"
}, {
"id": 56,
"Title": "USA"
}, {
"id": 89,
"Title": "England"
}]
function test(myJSON) {
// maybe parse my the JSON variable?
// and then I want to loop through it and access my IDs and my titles
}
Any suggestions how I can solve it?
This isn't a single JSON object. You have an array of JSON objects. You need to loop over array first and then access each object. Maybe the following kickoff example is helpful:
var arrayOfObjects = [{
"id": 28,
"Title": "Sweden"
}, {
"id": 56,
"Title": "USA"
}, {
"id": 89,
"Title": "England"
}];
for (var i = 0; i < arrayOfObjects.length; i++) {
var object = arrayOfObjects[i];
for (var property in object) {
alert('item ' + i + ': ' + property + '=' + object[property]);
}
// If property names are known beforehand, you can also just do e.g.
// alert(object.id + ',' + object.Title);
}
If the array of JSON objects is actually passed in as a plain vanilla string, then you would indeed need eval() here.
var string = '[{"id":28,"Title":"Sweden"}, {"id":56,"Title":"USA"}, {"id":89,"Title":"England"}]';
var arrayOfObjects = eval(string);
// ...
To learn more about JSON, check MDN web docs: Working with JSON
.
This is your dataArray:
[
{
"id":28,
"Title":"Sweden"
},
{
"id":56,
"Title":"USA"
},
{
"id":89,
"Title":"England"
}
]
Then parseJson can be used:
$(jQuery.parseJSON(JSON.stringify(dataArray))).each(function() {
var ID = this.id;
var TITLE = this.Title;
});
By 'JSON array containing objects' I guess you mean a string containing JSON?
If so you can use the safe var myArray = JSON.parse(myJSON) method (either native or included using JSON2), or the usafe var myArray = eval("(" + myJSON + ")"). eval should normally be avoided, but if you are certain that the content is safe, then there is no problem.
After that you just iterate over the array as normal.
for (var i = 0; i < myArray.length; i++) {
alert(myArray[i].Title);
}
Your question feels a little incomplete, but I think what you're looking for is a way of making your JSON accessible to your code:
if you have the JSON string as above then you'd just need to do this
var jsonObj = eval('[{"id":28,"Title":"Sweden"}, {"id":56,"Title":"USA"}, {"id":89,"Title":"England"}]');
then you can access these vars with something like jsonObj[0].id etc
Let me know if that's not what you were getting at and I'll try to help.
M
#Swapnil Godambe
It works for me if JSON.stringfy is removed.
That is:
$(jQuery.parseJSON(dataArray)).each(function() {
var ID = this.id;
var TITLE = this.Title;
});
var datas = [{"id":28,"Title":"Sweden"}, {"id":56,"Title":"USA"}, {"id":89,"Title":"England"}];
document.writeln("<table border = '1' width = 100 >");
document.writeln("<tr><td>No Id</td><td>Title</td></tr>");
for(var i=0;i<datas.length;i++){
document.writeln("<tr><td>"+datas[i].id+"</td><td>"+datas[i].Title+"</td></tr>");
}
document.writeln("</table>");

Categories