Easiest way to interate over a complex JSON object via Javascript - javascript

I'm consuming JSON data that has a bit of a weird structure for example:
{
"RESULT":
{
"COLUMNS": ["ID","name","ENABLED","perms","vcenabled","vcvalue","checkenabled","checkvalue","indxenabled","indxvalue"],
"DATA": [
[7,"Site-A", 1, "1,2", 1, 1, 1, 0, 0, 0],
[15,"Site-B", 1, "1,2,3,4", 1, 1, 1, 0, 0, 0]
]
},
"ERROR": 0
}
I would like to create some JavaScript that would restructure this data to proper JSON structures so that the "Column" array values become the keys for the "DATA" array's values. So after a JS process is run the data resembles the following:
[
{"ID":7,"name":"Site-A","ENABLED":1,"perms":"1,2","vcenabled":1,"vcvalue":1,"checkenabled":1,"checkvalue":1,"indxenabled":1,"indxvalue":1},
{"ID":15,"name":"Site-B","ENABLED":1,"perms":"1,2","vcenabled":1,"vcvalue":1,"checkenabled":1,"checkvalue":1,"indxenabled":1,"indxvalue":1}
]
What are the JavaScript best practices for accomplishing the JSON restructuring? Could I accomplish this task using a JS framework like JQuery, Foundation JS, ect... ?

Using Underscore, it's a one-liner:
var formatted = _.map(orig.RESULT.DATA, _.partial(_.object, orig.RESULT.COLUMNS));
With plain javascript (less elegant but faster), it would be
var formatted = [],
data = orig.RESULT.DATA,
cols = orig.RESULT.COLUMNS,
l = cols.length;
for (var i=0; i<data.length; i++) {
var d = data[i],
o = {};
for (var j=0; j<l; j++)
o[cols[j]] = d[j];
formatted.push(o);
}

newjson is your new object, j is your json,
code is very fast as it caches the legth and don't uses push.
And as it's pure javascript it's faster than all the libraries.
var j={
"RESULT":{
"COLUMNS":[
"ID",
"name",
"ENABLED",
"perms",
"vcenabled",
"vcvalue",
"checkenabled",
"checkvalue",
"indxenabled",
"indxvalue"
],
"DATA":[
[7,"Site-A", 1, "1,2", 1, 1, 1, 0, 0, 0],
[15,"Site-B", 1, "1,2,3,4", 1, 1, 1, 0, 0, 0]
]
},
"ERROR": 0
}
var newjson=[],d=j.RESULT.COLUMNS.length;
for(var a=0,b=j.RESULT.DATA.length;a<b;a++){
for(var c=0,tmpObj={};c<d;c++){
tmpObj[j.RESULT.COLUMNS[c]]=j.RESULT.DATA[a][c];
}
newjson[a]=tmpObj;
}
console.log(newjson);
based on Bergi's response u can also use the while-- loop.
var orig={
"RESULT":{
"COLUMNS":[
"ID",
"name",
"ENABLED",
"perms",
"vcenabled",
"vcvalue",
"checkenabled",
"checkvalue",
"indxenabled",
"indxvalue"
],
"DATA":[
[7,"Site-A", 1, "1,2", 1, 1, 1, 0, 0, 0],
[15,"Site-B", 1, "1,2,3,4", 1, 1, 1, 0, 0, 0]
]
},
"ERROR": 0
}
var formatted = [],
data = orig.RESULT.DATA,
cols = orig.RESULT.COLUMNS,
l = cols.length,
f = data.length;
while (f--) {
var d = data[f],
o = {},
g = l;
while (g--) {
o[cols[g]] = d[g];
}
formatted[f] = o;
}

you can use underscore Array functions for this task
http://underscorejs.org/#arrays
uusing the object function would be helpful
http://underscorejs.org/#object
from the documentation :
_.object(list, [values])
Converts arrays into objects. Pass either a single list of [key, value] pairs, or a list of keys, and a list of values ..the example:
_.object(['moe', 'larry', 'curly'], [30, 40, 50]);
=> {moe: 30, larry: 40, curly: 50}
here is the JSfiddle with the solution
http://jsfiddle.net/rayweb_on/kxR88/1/
and the code looks like this for this specific scenario.
var plain = {
"RESULT":
{
"COLUMNS": ["ID","name","ENABLED","perms","vcenabled","vcvalue","checkenabled","checkvalue","indxenabled","indxvalue"],
"DATA": [
[7,"Site-A", 1, "1,2", 1, 1, 1, 0, 0, 0],
[15,"Site-B", 1, "1,2,3,4", 1, 1, 1, 0, 0, 0]
]
},
"ERROR": 0
},
formatted = [];
_.each(plain.RESULT.DATA, function(value) {
var tmp = {};
tmp = _.object(plain.RESULT.COLUMNS,value)
formatted.push(tmp);
});
console.log(formatted);

Try this using underscorejs.
var plain = {
"RESULT":
{
"COLUMNS": ["ID","name","ENABLED","perms","vcenabled","vcvalue","checkenabled","checkvalue","indxenabled","indxvalue"],
"DATA": [
[7,"Site-A", 1, "1,2", 1, 1, 1, 0, 0, 0],
[15,"Site-B", 1, "1,2,3,4", 1, 1, 1, 0, 0, 0]
]
},
"ERROR": 0
}
, formatted = [];
_.each(plain.RESULT.DATA, function(value) {
var tmp = {};
_.each(value, function(parameter, pos) {
tmp[plain.RESULT.COLUMNS[pos]] = parameter;
});
formatted.push(tmp);
});
console.log(formatted);
http://jsfiddle.net/kxR88/

Actually, you could use a combination of Array#map for the array and Array#reduce for the objects with the new properties
var data = { RESULT: { COLUMNS: ["ID", "name", "ENABLED", "perms", "vcenabled", "vcvalue", "checkenabled", "checkvalue", "indxenabled", "indxvalue"], DATA: [[7, "Site-A", 1, "1,2", 1, 1, 1, 0, 0, 0], [15, "Site-B", 1, "1,2,3,4", 1, 1, 1, 0, 0, 0]] }, ERROR: 0 },
result = data.RESULT.DATA.map(function (a) {
return a.reduce(function (o, d, i) {
o[data.RESULT.COLUMNS[i]] = d;
return o;
}, {});
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
With ES6, you could use Object.assign with spread syntax ....
Object.assign adds properties to the given object and returns this object.
Spread syntax ... takes an array and insert the elements as parameters to the function.
var data = { RESULT: { COLUMNS: ["ID", "name", "ENABLED", "perms", "vcenabled", "vcvalue", "checkenabled", "checkvalue", "indxenabled", "indxvalue"], DATA: [[7, "Site-A", 1, "1,2", 1, 1, 1, 0, 0, 0], [15, "Site-B", 1, "1,2,3,4", 1, 1, 1, 0, 0, 0]] }, ERROR: 0 },
result = data.RESULT.DATA.map(a =>
Object.assign(...data.RESULT.COLUMNS.map((k, i) => ({ [k]: a[i] }))));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Using JQuery:
function jsonToObj(json){
return jQuery.parseJSON(JSON.stringify(json));
}
For example, after a GET request the server send a complex object
$.get("/Files/-2", function (rxData, status) {
var obj = jsonToObj(rxData);
console.log(obj);
});
Logged in console, can be explored through Chrome's Web Developer (F12), in my case looks like this:
image showing nested levels

By simple JS, your solution would look like this:
var yourObj = {
"RESULT": {
"COLUMNS": ["ID","name","ENABLED","perms","vcenabled","vcvalue","checkenabled","checkvalue","indxenabled","indxvalue"],
"DATA": [
[7,"Site-A", 1, "1,2", 1, 1, 1, 0, 0, 0],
[15,"Site-B", 1, "1,2,3,4", 1, 1, 1, 0, 0, 0]
]
},
"ERROR": 0
}
//Solution
var finalARR = [];
var colLength = yourObj.RESULT.COLUMNS.length;
var dataLength = yourObj.RESULT.DATA.length;
for (var i = 0; i < dataLength; i++) {
var finalJSON = {};
for (var j = 0; j < colLength; j++) {
finalJSON[yourObj.RESULT.COLUMNS[j]] = yourObj.RESULT.DATA[i][j];
}
finalARR[i] = finalJSON;
}
console.log(finalARR);

Related

Data extract from and object issue javascript

I have json data like
[ [ RowDataPacket { content_id: 52 } ],
OkPacket {
fieldCount: 0,
affectedRows: 0,
insertId: 0,
serverStatus: 2,
warningCount: 0,
message: '',
protocol41: true,
changedRows: 0 } ]
How I get content_id part from this data set?
I got this data while calling a Stored Procedure using TypeORM.
here is the code I tried
const contentData = await connection.getRepository(Content).query('CALL getInitialContent()');
To be a valid JS object literal, your data would have to look like this:
[
[ { RowDataPacket: { content_id: 52 } } ],
{ OkPacket: { fieldCount: 0, affectedRows: 0, insertId: 0, serverStatus: 2, warningCount: 0, message: '', protocol41: true, changedRows: 0}
}
];
Once you have that, then getting the content_id field is reasonably trivial as long as you can comprehend the data structure - it's inside the first element of an array, which itself is an array. The first element of that inner array is an object. That then contains another object inside the "RowDataPacket" object, and and the content_id data you want is a property of that second object.
Shorthand version:
let data = [
[{
RowDataPacket: {
content_id: 52
}
}],
{
OkPacket: {
fieldCount: 0,
affectedRows: 0,
insertId: 0,
serverStatus: 2,
warningCount: 0,
message: '',
protocol41: true,
changedRows: 0
}
}
];
let id = data[0][0].RowDataPacket.content_id;
console.log(id);
Longhand (so you can see the traversal of the data hierarchy step by step):
let data = [
[{
RowDataPacket: {
content_id: 52
}
}],
{
OkPacket: {
fieldCount: 0,
affectedRows: 0,
insertId: 0,
serverStatus: 2,
warningCount: 0,
message: '',
protocol41: true,
changedRows: 0
}
}
];
let arr = data[0]; //get inner array
let obj = arr[0]; //get object inside the array
let packetObj = obj.RowDataPacket; //get object in the RowDataPacket property
let id = packetObj.content_id; //get the target data
console.log(id);

How to get specific keys from object? (JS)

I have this object:
728394 : {
"playersAmount" : 2,
"players" : {
"LRFe9w9MQ6hf1urjAAAB" : {
"nickname" : "spieler1",
"type" : "player1"
},
"nKUDWEd5p_FCBO4sAAAD" : {
"nickname" : "spieler2",
"type" : "player2"
},
"ghdaWSWUdg27sf4sAAAC" : {
"nickname" : "spieler3",
"type" : "spectator"
}
},
"activePlayer" : "LRFe9w9MQ6hf1urjAAAB",
"board" : [
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0]
]
}
How do I get everything of the object above except for the k/v pair "board"? is there any other way than just adding every key except the right one?
You can create a copy and then delete the unwanted key:
const copy = { ...original }
delete copy.unwantedProperty
Of course you can instead delete the property on the original if you don't care about mutating it.
(Note: if your environment doesn't support the syntax { ...original }, you can use Object.assign({}, original) instead.)
EDIT: Actually, this answer is even neater.
const { board, ...everythingButBoard } = yourObject
simple answer will be:
const copyObject = Object.assign({}, yourObject) // to make a copy of original variable
delete copyObject['keyToRemove'] // OR delete copyObject.keyToRemove
else if you want to delete from original variable:
delete yourObject['keyToRemove'] // OR delete yourObject.keyToRemove
I think you can create a new object excluding this key using a for...in
object = {
wantedKey: 'wantedValue',
wantedKey2: 'wantedValue2',
wantedKey3: 'wantedValue3',
unwantedKey: 'unwantedValue'
}
const newObject = {}
for (const key in object) {
if (key !== 'unwantedKey') newObject[key] = object[key]
}
console.log(newObject)
for more info about for...in: click here

Generate valid output from array values in Javascript

Maybe this isn't the right place to ask this but I need a advice since I'm stuck on this. I have this code:
$(document).ready(function(){
var i = 0, j = 0,
manufacturerIds = [1,2,3,4,5,6,7],
countryIds = [1,2,3,4,5,6,7,8,9,10],
result = [];
for (i; i < manufacturerIds.length; i++) {
for (j; j < countryIds.length; j++) {
result.push({
i: {
idMan: manufacturerIds[i],
idCtr: [] // stuck on this point, don't know
// where to go from here and don't know
// if I'm doing things right
}
});
}
}
});
And I'm trying to return a output like this:
[
{
"0": {
"idMan": 1,
"idCtr": [
1,
2,
3,
4,
5
]
},
"1": {
"idMan": 2,
"idCtr": [
1,
2,
3,
4,
5
]
},
"2": {
"idMan": 3,
"idCtr": [
1,
2,
3,
4,
5
]
}
}
]
Can any give me some advice? Or help?
NOTE: I'm not sure this is the right or best way but I'm trying to build some kind of structure where I can differentiate each item on the object|array, why? Because I'll need to add new element to it. For example, this ouput will be valid too:
[
{
"0": {
"idMan": 1,
"idCtr": [
1,
2
]
},
"1": {
"idMan": 1,
"idCtr": [
1,
4,
5
]
},
"2": {
"idMan": 1,
"idCtr": [
3
]
}
}
]
Then having this I think will be easy to add new idCtr right? By accesing someVar[X].idCtr.push(newVal);. BTW, I write some var examples but the truth is those values are dynamic, just a start point for you to get the idea behind my doubt
I believe this is more along the lines of what you are wanting
var i = 0,
j = 0,
manufacturerIds = [1, 2, 3, 4, 5, 6, 7],
countryIds = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
result = [];
for (i; i < manufacturerIds.length; i++) {
/* create basic object*/
var item = {};
item[i] = {idMan: manufacturerIds[i],idCtr: []};
/* now push country Ids*/
for (var j=0;; j < countryIds.length; j++) {
item[i].idCtr.push(countryIds[j]);
}
/* finished creating object*/
result.push(item);
}
DEMO
You can use JSON.stringify() to convert the result to JSON. There is another problem with i: {} try something like this:
$(document).ready(function(){
var i = 0, j = 0,
manufacturerIds = [1,2,3,4,5,6,7],
countryIds = [1,2,3,4,5,6,7,8,9,10],
result = [];
for (i; i < manufacturerIds.length; i++) {
var obj = {};
obj[i] = { idMan: manufacturerIds[i], idCtr: [] };
for (j; j < countryIds.length; j++) {
obj[i].idCtr.push(countryIds[j]);
}
result.push(obj);
}
var data = JSON.stringify(result);
});

How can I merge two array of objects and concatenate values?

I have this two array of objects
var client = [{
"creazione": "1970-01-01",
"value": 2
}, {
"creazione": "2014-03-12",
"value": 4
}, {
"creazione": "2014-03-14",
"value": 1
}],
order = [{
"creazione": "1970-01-01",
"value": 1
}, {
"creazione": "2014-03-13",
"value": 5
}, {
"creazione": "2014-03-14",
"value": 1
}];
I need to merge these two arrays to get something like:
[{
x: '1970-01-01',
y: [2, 1]
}, {
x: '2014-03-12',
y: [4, 0]
}, {
x: '2014-03-14',
y: [1, 1]
}, {
x: '2014-03-13',
y: [0, 5]
}]
In few words I need to check if a.creazione == b.creazione then merge the key and concat the values in an array (first line of result), else if it is different, assign the value of the existing array in the right position of the y array (third line of result).
PS: I need to get this structure beacuse I'm using Angular-Charts library, and it ask for data in this uncomfortable way.
Any idea on how to achieve this?
Allow me to amuse you with the power of functional programming :)
client = _.object(_.map(client, _.values));
order = _.object(_.map(order , _.values));
var result = _
.chain(_.keys(client))
.union(_.keys(order))
.map(function (key) {
return [key, [client[key] || 0, order[key] || 0]];
})
.map(_.partial(_.zipObject, ['x', 'y']))
.value();
console.log(result);
# [ { x: '1970-01-01', y: [ 2, 1 ] },
# { x: '2014-03-12', y: [ 4, 0 ] },
# { x: '2014-03-14', y: [ 1, 1 ] },
# { x: '2014-03-13', y: [ 0, 5 ] } ]
Using plain JavaScript:
var result = [];
client.forEach( function( entry ) {
for( var i = 0; i < order.length; ++i ) {
if( entry.creazione === order[i].creazione ) {
result.push( { x: entry.creazione, y: [ entry.value, order[i].value ] } );
order.splice( i, 1 );
return;
}
}
result.push( { x: entry.creazione, y: [ entry.value, 0 ] } );
} );
order.forEach( function( entry ) {
result.push( { x: entry.creazione, y: [ 0, entry.value ] } );
} );
Fiddle: http://jsfiddle.net/rPk6e/
Note that for simplicity the order array is modified. If that is a problem for your use case simply make a copy using slice.

Javascript and Arrays

This i have to admin has always been my Achilles tendon despite my years of experience in programming.
I have a json result looking like this from which I want to draw a time series using highcharts.com
[{"iso-2":"DE","year":"2000","value":"0"},{"iso-2":"FR","year":"2000","value":"0"},{"iso-2":"KE","year":"2000","value":"0"},{"iso-2":"DE","year":"2001","value":"0"},{"iso-2":"FR","year":"2001","value":"0"},{"iso-2":"KE","year":"2001","value":"0"},{"iso-2":"DE","year":"2002","value":"0"},{"iso-2":"FR","year":"2002","value":"0"},{"iso-2":"KE","year":"2002","value":"0"},{"iso-2":"DE","year":"2003","value":"9355"},{"iso-2":"FR","year":"2003","value":"19490"},{"iso-2":"KE","year":"2003","value":"0"},{"iso-2":"DE","year":"2004","value":"0"},{"iso-2":"FR","year":"2004","value":"0"},{"iso-2":"KE","year":"2004","value":"0"},{"iso-2":"DE","year":"2005","value":"11"},{"iso-2":"FR","year":"2005","value":"8"},{"iso-2":"KE","year":"2005","value":"0"},{"iso-2":"DE","year":"2006","value":"2"},{"iso-2":"FR","year":"2006","value":"1388"},{"iso-2":"KE","year":"2006","value":"0"},{"iso-2":"DE","year":"2007","value":"0"},{"iso-2":"FR","year":"2007","value":"0"},{"iso-2":"KE","year":"2007","value":"0"}]
I'd like to dynamically generate the above result into an arrays that looks like this
series: [{
name: 'KE',
data: [0,0,0,0,0,0,0,0]
}, {
name: 'FR',
data: [0,0,0,19490,0,8,1388,0]
}, {
name: 'DE',
data: [0,0,0,9355,0,2,0]
}]
Thank you so much for looking into this
var gathered = data.reduce(function(prev, curr) {
if (prev.hasOwnProperty(curr["iso-2"])) {
prev[curr["iso-2"]].push(parseInt(curr["value"]));
} else {
prev[curr["iso-2"]] = [parseInt(curr["value"])];
}
return prev;
}, {});
var result = [];
for (var country in gathered) {
var obj = {};
obj["name"] = country;
obj["data"] = gathered[country];
result.push(obj);
}
console.log(result);
Output
[ { name: 'DE', data: [ 0, 0, 0, 9355, 0, 11, 2, 0 ] },
{ name: 'FR', data: [ 0, 0, 0, 19490, 0, 8, 1388, 0 ] },
{ name: 'KE', data: [ 0, 0, 0, 0, 0, 0, 0, 0 ] } ]
Here's what I can think of, considering the data you have in the JSON is sorted by year:
var json_data = '[{"iso-2":"DE","year":"2000","value":"0"},...]'; // This is the json data you have.
var data = JSON.parse(json_data); // Convert JSON data to javascript object or array
// Organize the data in an object
var organized = {};
data.forEach(function (item){
if (typeof organized[item['iso-2']] !== 'undefined'){
organized[item['iso-2']].push(item['value']);
} else {
organized[item['iso-2']] = [item['value']];
}
});
// Convert the object to the format you need
var series = [];
for (i in organized){
series.push({
name: i,
data: organized[i]
});
}

Categories

Resources