Javascript/Jquery JSON object to array inside object - javascript

I see many topics on this site, but every one deal with single Array.
My need is to convert every object with number as key to array.
For exemple,
I have an object like :
{
"parent":{
"0":{
"child":false
},
"1":{
"child":false
},
"4": {
"child":false
}
}
}
And i would like
{
"parent": [
{
"child":false
},
{
"child":false
},
null,
null,
{
"child":false
}
]
}
This is an exemple, my object can be really deep and content many object like this, so i need a generic function.
UPDATE
My try sor far using code of #Nenad Vracar :
function recursiveIteration(object) {
var newob = {};
for (var property in object) {
if (object.hasOwnProperty(property)) {
if (typeof object[property] == "object"){
var result = {};
var keys = Object.keys(object[property]);
if ($.isNumeric(keys[0])) {
console.log("======> "+property+" is table");
for (var i = 0; i <= keys[keys.length - 1]; i++) {
if (keys.indexOf(i.toString()) != -1) {
result[property] = (result[property] || []).concat(object[property][i]);
} else {
result[property] = (result[property] || []).concat(null);
}
}
newob[property] = result;
recursiveIteration(object[property]);
}
newob[property] = object[property];
recursiveIteration(object[property]);
}else{
newob[property] = object[property];
}
}
}
return newob;
}
And the JSFiddle for live try
Thanks you guys !

I think this is what you want:
var data = {
"parent": {
"0": {
"child": false
},
"1": {
"child": false
},
"4": {
"child": false
}
}
};
var convert = function(data) {
// not an object, return value
if (data === null || typeof data !== 'object')
return data;
var indices = Object.keys(data);
// convert children
for (var i = 0; i < indices.length; i++)
data[indices[i]] = convert(data[indices[i]]);
// check if all indices are integers
var isArray = true;
for (var i = 0; i < indices.length; i++) {
if (Math.floor(indices[i]) != indices[i] || !$.isNumeric(indices[i])) {
isArray = false;
break;
}
}
// all are not integers
if (!isArray) {
return data;
}
// all are integers, convert to array
else {
var arr = [];
for (var i = 0, n = Math.max.apply(null, indices); i <= n; i++) {
if (indices.indexOf(i.toString()) === -1)
arr.push(null);
else
arr.push(data[i]);
}
return arr;
}
};
console.log( convert(data) );
Here is a working jsfiddle with the data you provided in the update.

You can do this with Object.keys() and one for loop
var data = {"parent":{"0":{"child":false},"1":{"child":false},"4":{"child":false}}}, result = {}
var keys = Object.keys(data.parent);
for (var i = 0; i <= keys[keys.length - 1]; i++) {
if (keys.indexOf(i.toString()) != -1) {
result.parent = (result.parent || []).concat(data.parent[i]);
} else {
result.parent = (result.parent || []).concat(null);
}
}
console.log(result)

You might achieve this job with a very simple recursive Object method as follows. Any valid nested object (including arrays) within an object structure will be converted into an array, in which the properties are replaced with indices and values are replaced by items.
Object.prototype.valueToItem = function(){
return Object.keys(this).map(e => typeof this[e] === "object" &&
this[e] !== null &&
!Array.isArray(this[e]) ? this[e].valueToItem()
: this[e]);
};
var o = { name: "terrible",
lastname: "godenhorn",
cars: ["red barchetta", "blue stingray"],
age: 52,
child: { name: "horrible",
lastname: "godenhorn",
cars: ["fiat 124", "tata"],
age: 24,
child:{ name: "badluck",
lastname: "godenhorn",
cars: ["lamborghini countach"],
age: 2,
child: null}}},
a = o.valueToItem();
console.log(a);
Ok modified to the OP's conditions but still generic as much as it can be.
Object.prototype.valueToItem = function(){
var keys = Object.keys(this);
return keys.reduce((p,c) => typeof this[c] === "object" &&
this[c] !== null &&
!Array.isArray(this[c]) ? keys.every(k => Number.isInteger(k*1)) ? (p[c] = this[c].valueToItem(),p)
: this[c].valueToItem()
: this
,new Array(~~Math.max(...keys)).fill(null));
};
var o = {
parent: {
0: {
child : false
},
1: {
child : false
},
4: {
child : {
0: {
child : false
},
3: {
child : false
},
5: {
child : false
}
}
}
}
};
a = o.valueToItem();
console.log(JSON.stringify(a,null,4));

Related

Format a javascript object into a specific structure

i have a javascript object as follows
obj = {"account_id-0":null,"option_item_id-0":1,"value-0":"wer","account_id-1":null,"option_item_id-1":2,"value-1":"kkk","account_id-2":null,"option_item_id-2":3,"value-2":"qqqqq"
....
"account_id-n":null,"option_item_id-n":6,"value-n":"see"
}
From the above object, i need to create the following structure
{"0": {
account_id: null,
option_item_id: 1,
value: "wer"
},
"1": {
account_id: null,
option_item_id: 2,
value: "kkk"
},
"2": {
account_id: null,
option_item_id: 2,
value: "qqqqq"
},
.
.
.
"n": {
account_id: null,
option_item_id: 6,
value: "see"
}
}
Any idea on how to implement this?
You can iterate through the all the keys, and use Array#reduce to contruct the resultant object.
let obj = {
"account_id-0": null,
"option_item_id-0": 1,
"value-0": "wer",
"account_id-1": null,
"option_item_id-1": 2,
"value-1": "kkk",
"account_id-2": null,
"option_item_id-2": 3,
"value-2": "qqqqq",
"account_id-n": null,
"option_item_id-n": 6,
"value-0": "see"
};
let result = Object.keys(obj).reduce((res, item) => {
let [key, index] = item.split('-');
if (!res[index]) {
res[index] = {};
}
res[index][key] = obj[item];
return res;
}, {});
console.log(result);
var obj = {
"account_id-0": null,
"option_item_id-0": 1,
"value-0": "wer",
"account_id-1": null,
"option_item_id-1": 2,
"value-1": "kkk",
"account_id-2": null,
"option_item_id-2": 3,
"value-2": "qqqqq"
};
var props = [];
function getObj(ind) {
for (var p in props) {
if (ind === p) {
return props[p];
}
}
}
for (var prop in obj) {
var parts = prop.split('-');
var key = parts[0];
var indx = parts[1];
var tmp = getObj(indx);
if (tmp == undefined) {
var x = {};
x[indx] = {};
x[indx][key] = obj[prop];
props.push(x);
} else {
tmp[indx][key] = obj[prop];
}
}
console.log(props);
This should be the straight forward way of maniplulating the object array with simple split() function.
Try this:
var keys = Object.keys(obj), i = 0
var arr = [], o = {}
for(var k in keys) {
if(keys[k].match(/\d*$/m) == i) {
o[keys[k].replace(/-\d*$/m,'')] = obj[keys[k]]
} else {
i++
arr.push(o)
o = {}
}
}
Here I am using an array instead of an object with the keys "0", "1", " 2", ... "n". I think it's way more convenient.

How can I filter a JSON object in JavaScript?

I've got the following JSON string:
{
"Alarm":{
"Hello":48,
"World":3,
"Orange":1
},
"Rapid":{
"Total":746084,
"Fake":20970,
"Cancel":9985,
"Word": 2343
},
"Flow":{
"Support":746084,
"About":0,
"Learn":0
}
}
Then I load the above string and convert it to json object:
jsonStr = '{"Alarm":{"Hello":48,"World":3,"Orange":1},"Rapid":{"Total":746084,"Fake":20970,"Cancel":9985},"Flow":{"Support":746084,"About":0,"Learn":0}}';
var jsonObj = JSON.parse(jsonStr);
Now, how can I filter this json object by key name?
E.g., if the filter was "ange", the filtered object would be:
{
"Alarm":{
"Orange":1
}
}
If the filter was "flo", the filtered object would become:
{
"Flow":{
"Support":746084,
"About":0,
"Learn":0
}
}
And if the filter was "wor", the result would be:
{
"Alarm":{
"World": 3,
},
"Rapid":{
"Word": 2343
}
}
Is it possible to achieve this filtering using the filter method?
Beside the given solutions, you could use a recursive style to check the keys.
This proposal gives the opportunity to have more nested objects inside and get only the filtered parts.
function filterBy(val) {
function iter(o, r) {
return Object.keys(o).reduce(function (b, k) {
var temp = {};
if (k.toLowerCase().indexOf(val.toLowerCase()) !== -1) {
r[k] = o[k];
return true;
}
if (o[k] !== null && typeof o[k] === 'object' && iter(o[k], temp)) {
r[k] = temp;
return true;
}
return b;
}, false);
}
var result = {};
iter(obj, result);
return result;
}
var obj = { Alarm: { Hello: 48, "World": 3, Orange: 1 }, Rapid: { Total: 746084, Fake: 20970, Cancel: 9985, Word: 2343 }, Flow: { Support: 746084, About: 0, Learn: 0 }, test: { test1: { test2: { world: 42 } } } };
console.log(filterBy('ange'));
console.log(filterBy('flo'));
console.log(filterBy('wor'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can create a function using reduce() and Object.keys() that will check key names with indexOf() and return the desired result.
var obj = {
"Alarm": {
"Hello": 48,
"World": 3,
"Orange": 1
},
"Rapid": {
"Total": 746084,
"Fake": 20970,
"Cancel": 9985,
"Word": 2343
},
"Flow": {
"Support": 746084,
"About": 0,
"Learn": 0
}
}
function filterBy(val) {
var result = Object.keys(obj).reduce(function(r, e) {
if (e.toLowerCase().indexOf(val) != -1) {
r[e] = obj[e];
} else {
Object.keys(obj[e]).forEach(function(k) {
if (k.toLowerCase().indexOf(val) != -1) {
var object = {}
object[k] = obj[e][k];
r[e] = object;
}
})
}
return r;
}, {})
return result;
}
console.log(filterBy('ange'))
console.log(filterBy('flo'))
console.log(filterBy('wor'))
With the filter method I think you mean the Array#filter function. This doesn't work for objects.
Anyway, a solution for your input data could look like this:
function filterObjects(objects, filter) {
filter = filter.toLowerCase();
var filtered = {};
var keys = Object.keys(objects);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (objects.hasOwnProperty(key) === true) {
var object = objects[key];
var objectAsString = JSON.stringify(object).toLowerCase();
if (key.toLowerCase().indexOf(filter) > -1 || objectAsString.indexOf(filter) > -1) {
filtered[key] = object;
}
}
}
return filtered;
}

Sorting trees recursively

I want to sort children for each root inside my object tree - how can I do this?
The tree:
{
folder: { id: 1, name: 'root' },
children: [
{
folder: { id: 2, parentId: 1, name: 'zzz' },
children: []
},
{
element: { id: 1, name: 'aaa' },
children: []
}
]
}
Sorting it would swap folder and element here, etc. The actual tree is much bigger, with much higher depth. How can I do this?
I have an algorithm finding something in this tree:
/**
* searchFor {
* type: '',
* index: '',
* value: ''
* }
*/
var search = function (data, searchFor) {
if (data[searchFor.type] != undefined &&
data[searchFor.type][searchFor.index] == searchFor.value) {
return data;
} else if (data.children != null) {
var result = null;
for (var i = 0; result == null && i < data.children.length; i++) {
result = search(data.children[i], searchFor);
}
return result;
}
return null;
};
But I honestly have no idea how can I just sort it. How should I do this?
I have tried something like this, but it doesn't work:
/**
* sortBy {
* type: '',
* index: '',
* order: '' // asc/desc
* }
*/
var sort = function (data, sortBy) {
if (data.children != null) {
// sort all children here, but how?
var result = null;
for (var i = 0; result == null && i < data.children.length; i++) {
result = search(data.children[i], sortBy);
}
return result;
}
return null;
}
This should work.
function sortTree(tree){
tree.children.sort(function(a,b){
if (a.folder !== undefined && b.folder === undefined) return -1;
if (a.folder === undefined && b.folder !== undefined) return 1;
a = a.folder === undefined ? a.element;
b = b.folder === undefined ? b.element;
if (a.name == b.name) return 0;
return a.name < b.name ? -1 : 1;
});
for (i = 0; i < tree.children.length){
sortTree(tree.children[i])
}
}

Generate array of parameters and sub-parameters of JSDoc

I'm extending the haruki template to support sub parameters.
My JSDoc comment is:
/**
* #constructor Foobar
* param {Object} firstLevel
* param {Object} [firstLevel.secondLevel]
* param {Object} [firstLevel.secondLevel.thirdLevel]
*/
By default, haruki will export a flat array of parameters like this:
[
{ name: 'firstLevel' },
{ name: '[firstLevel.secondLevel]' },
{ name: '[firstLevel.secondLevel.thirdLevel]' }
]
But I need to get an output like this:
[
{
name: 'firstLevel',
parameters: [
{
name: 'secondLevel',
parameters: [
{ name: 'thirdLevel' }
]
}
]
}
My idea was to create an Object and then convert it to Array, doing so I can easily access to the nested parameters.
But I can't find a solution to the recursiveness problem...
My attempt is the one below:
function subParam(paramsObj, names, paramObj) {
if (names.length === 1) {
paramsObj[names[0]] = paramObj;
} else {
paramsObj[names[0]].parameters[names[1]] = paramObj;
}
}
if (element.params) {
var params = {};
for (i = 0, len = element.params.length; i < len; i++) {
var names = element.params[i].name.replace(/\[|\]/g, '').split('.');
var obj = {
'name': element.params[i].name,
'type': element.params[i].type? element.params[i].type.names : [],
'description': element.params[i].description || '',
'default': hasOwnProp.call(element.params[i], 'defaultvalue') ? element.params[i].defaultvalue : '',
'optional': typeof element.params[i].optional === 'boolean'? element.params[i].optional : '',
'nullable': typeof element.params[i].nullable === 'boolean'? element.params[i].nullable : ''
};
subParam(params, names, obj);
}
// convert object to array somehow
}
Ideas?
In JavaScript, key-value pairs where key is unique are best suited for Object and not Array.
Create your tree in an Object, then re-structure it to your desired Array
function transform(data) {
var o = {}, i, str;
function addPath(path) {
var parts = path.split('.'),
e = o, i = 0;
for (; i < parts.length; ++i) {
e = e[parts[i]] = e[parts[i]] || {};
}
}
function transformPathObject(dir, obj) {
var key, arr = [];
for (key in obj) {
arr.push(transformPathObject(key, obj[key]));
}
obj = {'name': dir};
if (arr.length) obj.parameters = arr;
return obj;
}
for (i = 0; i < data.length; ++i) {
str = data[i].name;
str = str.replace(/^\[(.*)\]$|(.*)/, '$1$2');
addPath(str);
}
return transformPathObject('__root__', o).parameters;
}
Usage
var data = [
{ name: 'firstLevel' },
{ name: '[firstLevel.secondLevel]' },
{ name: '[firstLevel.secondLevel.thirdLevel]' }
];
transform(data);
/*
[
{
"name": "firstLevel",
"parameters": [
{
"name": "secondLevel",
"parameters": [
{
"name": "thirdLevel"
}
]
}
]
}
]
*/
Please note that you didn't show Optional data in your desired output

Loop through JSON object and check if particular object exists

I have a JSON object :
[{"box":1,"parent":[],"child":[{"boxId":2}]},{"box":2,"parent":[{"boxId":1}],"child":[]}]
I have a requirement where in I would like to check whether my JSON object has particular box; if yes then check if it has particular child.
eg: check if box 1 exists
if yes then
check if it has child
if yes then
check if it has child boxId=2
How do I do that in javascript/ jquery?
This is how I tried:
var DependantArr=myJSON;
var $hasDependancy;
DependantArr.map(function (boxes) {
if (boxes.box == 2) {
if (boxes.child.length != 0) {
boxes.child.map(function (child) {
$hasDependancy = true;
return false;
});
}
}
This doesn't seem to work as even after I return false it still continues to go in loop. I would like to break the loop if i find a match.
Any suggestion?
You need to iterate over all arrays, you need.
var array = [{ "box": 1, "parent": [], "child": [{ "boxId": 2 }] }, { "box": 2, "parent": [{ "boxId": 1 }], "child": [] }];
function check() {
var found = false;
array.some(function (a) {
if (a.box === 1) {
Array.isArray(a.child) && a.child.some(function (b) {
if (b.boxId === 2) {
found = true;
return true;
}
});
return true;
}
});
return found;
}
document.write(check());
Another solution features a more generic approach, with a given object, which acts as a pattern for the needed items.
[
{ condition: { box: 1 }, nextKey: 'child' },
{ condition: { boxId: 2 } }
]
var array = [{ "box": 1, "parent": [], "child": [{ "boxId": 2 }] }, { "box": 2, "parent": [{ "boxId": 1 }], "child": [] }];
function check(array, conditions) {
function c(a, index) {
var el = conditions[index],
k = Object.keys(el.condition),
v = el.condition[k],
found = false;
return Array.isArray(a) &&
a.some(function (b) {
if (b[k] === v) {
found = true;
if (conditions.length > index + 1) {
found = c(b[el.nextKey], index + 1);
}
return true;
}
}) &&
found;
}
return c(array, 0);
}
document.write(check(array, [{ condition: { box: 1 }, nextKey: 'child' }, { condition: { boxId: 2 } }])+'<br>');
document.write(check(array, [{ condition: { box: 2 }, nextKey: 'parent' }, { condition: { boxId: 1 } }]) + '<br>');
Create a function that will call the filter on your array and return it. The returned value would be an array containing the found object(s) which match(es) your condition(s).
Demo Snippet:
(check the console)
var json = [{"box":1,"parent":[],"child":[{"boxId":2}]},{"box":2,"parent":[{"boxId":1}],"child":[]}];
function search(id, childId) {
return json.filter(function(obj) {
if ((obj.box == id) && (obj.child) && (obj.child.length > 0)) {
return obj.child.filter(function(child) {
return (child.boxId == childId);
});
}
});
}
console.log(search('1', '2')[0]);
console.log(search('2', '2')[0]);
You can make use of recursion. call the same function recursively to check if the element you need is really exist in the array or not.
var json = [{"box":1,"parent":[],"child":[{"boxId":2}]},{"box":2,"parent":[{"boxId":1}],"child":[]}];
var found = false;
function validateJson(data, box, boxId){
for(key in data){
if((data[key].constructor === Object || data[key].constructor === Array) && (key !== box && data[key] !== 1 || key !== boxId && data[key] !== 2)){
arguments.callee(data[key]); // <---calls the same function again.
} else {
found = true; // true only in the case of if "box":1 and "boxId" : 2
}
}
return found;
}
var result = validateJson(json, "box", "boxId");
document.body.innerHTML = '<pre> found : '+JSON.stringify(result) + '</pre>';
Try this
data.forEach(function (el) {
Object.keys(el).forEach(function (property) {
if (el[property] === 'your value to check') {
// do whatever you need here
}
});
});
If this is the only case you need to check, you can use this:
var DependantArr = [{"box": 1, "parent": [], "child": [{"boxId": 3}]}, {"box": 2, "parent": [{"boxId": 1}], "child": []}];
var $hasDependancy = DependantArr.some(function(thisBox) {
if ((thisBox.box === 1) && (thisBox.hasOwnProperty('child'))) {
return thisBox.child.filter(function(thisChild) {
return thisChild.boxId === 2;
}).length > 0;
}
});
I think these will help.
for(var i=DependantArr.length;i>=0;i--) {
return DependantArr[i].box == 1 && DependantArr[i].child.length!=0 &&
DependantArr[i].child[0].boxId==2;
}

Categories

Resources