I have a this type of a json object.
{
"id": "001",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001"],
"children": [
{
"id": "002",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "002"],
"children": []
},
{
"id": "003",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "003"],
"children": [
{
"id": "00001",
"type": "B",
"children": []
}
]
},
{
"id": "004",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004"],
"children": [
{
"id": "005",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004", "005"],
"children": []
},{
"id": "005",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004", "005"],
"children": [
{
"id": "00002",
"type": "B",
"children": []
}
]
}
]
},
{
"id": "00003",
"type": "B",
"children": []
}
]
}
I need to replace all the object which is type: "B" , with this (which is mentioned below) type of object which I can get from an object with ids as keys of typed B. This typed B objects can be nested anywhere either as a first child or fifth child of a nested arrays of children
{
"id": "002",
"type": "A",
"value": "aaaaa",
"data:": {},
"children": []
},
How can I do that? This can be deeply nested and there's no specific place where we should replace the objects, beforehand. So, I need to go through the entire object and do that. How should I get it done?
EDIT
I updated the code in the question slightly. There's a path property of the nested in each object, except for typed B objects. So, when replacing the typed B properties with the other object, I need to add the paths in there as well.
eg: path for id: "00001", typed B object should be : ["001", "003", "00001"]
EDIT :
Expected result
{
"id": "001",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001"],
"children": [
{
"id": "002",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "002"],
"children": []
},
{
"id": "003",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "003"],
"children": [
{
"id": "002",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "003", "002"],
"children": []
},
]
},
{
"id": "004",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004"],
"children": [
{
"id": "005",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004", "005"],
"children": []
},{
"id": "005",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004", "005"],
"children": [
{
"id": "002",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "004", "005", "002"],
"children": []
}
]
}
]
},
{
"id": "002",
"type": "A",
"value": "aaaaa",
"data:": {},
"path": ["001", "002"],
"children": []
}
]
}
lodash if you don't mind.
Use cloneDeepWith to clone the entire tree and replace a specific value.
const data = {"id":"001","type":"A","value":"aaaaa","data:":{},"children":[{"id":"002","type":"A","value":"aaaaa","data:":{},"children":[]},{"id":"003","type":"A","value":"aaaaa","data:":{},"children":[{"id":"00001","type":"B","children":[]}]},{"id":"004","type":"A","value":"aaaaa","data:":{},"children":[{"id":"005","type":"A","value":"aaaaa","data:":{},"children":[]},{"id":"005","type":"A","value":"aaaaa","data:":{},"children":[{"id":"00002","type":"B","children":[]}]}]},{"id":"00003","type":"B","children":[]}]};
const result = _.cloneDeepWith(data, (value) => {
const newObj = {"id": "002", "type": "A", "value": "---NEW VALUE FOR 'B' TYPE---", "data:": {} };
return (value.type === 'B') ? { ...value, ...newObj} : _.noop();
});
console.dir(result, { depth: null } );
.as-console-wrapper{min-height: 100%!important; top: 0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.js" integrity="sha512-2iwCHjuj+PmdCyvb88rMOch0UcKQxVHi/gsAml1fN3eg82IDaO/cdzzeXX4iF2VzIIes7pODE1/G0ts3QBwslA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
--- Update 2--- (Without lodash)
Use local variable to store and combine current path.
const data = { "id": "001", "type": "A", "value": "aaaaa", "data:": {}, "path": ["001"], "children": [{ "id": "002", "type": "A", "value": "aaaaa", "data:": {}, "path": ["001", "002"], "children": [] }, { "id": "003", "type": "A", "value": "aaaaa", "data:": {}, "path": ["001", "003"], "children": [{ "id": "00001", "type": "B", "children": [] }] }, { "id": "004", "type": "A", "value": "aaaaa", "data:": {}, "path": ["001", "004"], "children": [{ "id": "005", "type": "A", "value": "aaaaa", "data:": {}, "path": ["001", "004", "005"], "children": [] }, { "id": "005", "type": "A", "value": "aaaaa", "data:": {}, "path": ["001", "004", "005"], "children": [{ "id": "00002", "type": "B", "children": [] }] }] }, { "id": "00003", "type": "B", "children": [] }] }
const deepReplace = (obj, prevPath = []) => {
if (obj.type === 'A') {
if (obj.children.length) {
obj.children = obj.children.map((childObj) => deepReplace(childObj, obj.path))
}
return obj;
};
if (obj.type === 'B') {
const id = '002';
return { id, type: "A", value: "aaaaa", path: [...prevPath, id], data: {}, children: []};
};
};
console.dir(deepReplace(data), { depth: null });
.as-console-wrapper{min-height: 100%!important; top: 0}
This looks like a tree traversal problem. Here's a way to handle that with depth-first search without recursion.
As mentioned in this answer, recursion should be avoided whenever possible, as it requires more memory and is more difficult to debug than an iterative implementation.
Updated per adjustment in question
const data = {"id":"001","type":"A","value":"aaaaa","data:":{},"path":["001"],"children":[{"id":"002","type":"A","value":"aaaaa","data:":{},"path":["001","002"],"children":[]},{"id":"003","type":"A","value":"aaaaa","data:":{},"path":["001","003"],"children":[{"id":"00001","type":"B","children":[]}]},{"id":"004","type":"A","value":"aaaaa","data:":{},"path":["001","004"],"children":[{"id":"005","type":"A","value":"aaaaa","data:":{},"path":["001","004","005"],"children":[]},{"id":"005","type":"A","value":"aaaaa","data:":{},"path":["001","004","005"],"children":[{"id":"00002","type":"B","children":[]}]}]},{"id":"00003","type":"B","children":[]}]};
const dfs = () => {
const stack = [[data, null]];
while(stack.length) {
const [curr, parent] = stack.pop();
// check for match on type
if (curr.type === "B") {
curr.type = "A";
curr.id = "002";
curr.value = "aaaaa";
curr.data = {};
curr.path = [...parent?.path.slice() ?? [], "002"];
}
curr.children.forEach(child => stack.push([child, curr]));
}
};
dfs();
const output = document.getElementById("output");
output.innerText = JSON.stringify(data, null, 2);
<pre id="output" />
I played around with this in the console and it did what you wanted (based on the json array provided, setting all the "B" to "A" types). It's a recursive function so on any nested child it meets in the "children" array it would call the function again on each item in the array.
function fixObjects (obj) {
if (obj["type"] === "B") {
obj["type"] = "A";
obj["id"] = "002";
obj["value"] = "aaaaa";
obj["data"] = {};
}
if (obj["children"].length > 0) {
obj["children"].forEach (child => fixObjects (child));
}
}
fixObjects (_yourArray)
const object1: [{
"code": "lap-143240121",
"index": 0
}, {
"code": "lap-15040293",
"index": 1
}, {
"code": "lp-1504444",
"index": 2
}, {
"code": "lp-150440987",
"index": 3
}]
const object2: [{
"code": "lap-143240121",
"name": "name1"
}, {
"code": "lap-15040293",
"name": "name2"
}, {
"code": "lp-1504444",
"name": "name3"
}]
I would like to map those two list of object by code to have an output like :
const objectResult: [{
"code": "lap-143240121",
"index": 0,
"name": "name1"
}, {
"code": "lap-15040293",
"index": 1,
"name": "name2"
}, {
"code": "lp-1504444",
"index": 2,
"name": "name3"
}]
Use map to iterate object2 and then use rest operator to return an object which consist of all the elements and the name from object1
const object1 = [{
"code": "lap-143240121",
"index": 0
}, {
"code": "lap-15040293",
"index": 1
}, {
"code": "lp-1504444",
"index": 2
}, {
"code": "lp-150440987",
"index": 3
}]
const object2 = [{
"code": "lap-143240121",
"name": "name1"
}, {
"code": "lap-15040293",
"name": "name2"
}, {
"code": "lp-1504444",
"name": "name3"
}];
const obj3 = object2.map((item) => {
return {
...item, // will consist all the items from object2
// get index from object1 where the code matches
index: object1.find(elem => elem.code === item.code).index
}
});
console.log(obj3)
transform the object1 to Map with value of code as key and whole object as value
iterate on object2 search code from object2 in the above created map, if found merge the properties
I have two objects obj1 and obj2, how to loop through array key children and if code name matches, then add the name key in the object obj2, get the object.
How to loop through object of objects and match the key and push the key to get the new object in javascript
function newObject(obj1, obj2) {
var result = obj1.map(e => {
if ('children' in e)
e.children = e.children.map(child => {
if ('children' in child)
child.children = child.children.map(c => {
name: c.name
});
return child;
});
return e;
})
return result
}
var obj1 = [{
"id": 1,
"item": "node1",
"children": [{
"id": 2,
"code": "countries",
"title": "Country",
"children": [{
"cid": 12,
"code": "S1",
"name": "SG",
"children": [{
"id": 4,
"code": "C1",
"name": "City"
}]
},
{
"cid": 13,
"code": "S2",
"name": "TH"
}
]
},
{
"id": 2,
"code": "Groceries",
"title": "Grocery",
"children": [{
"cid": 11,
"code": "G1",
"name": "Fruits"
},
{
"cid": 10,
"code": "G2",
"name": "Vegetables"
}
]
}, {
"id": 3,
"code": "lists",
"title": "Option"
}
]
}];
var obj2 = [{
id: 1,
code: "G1",
status: "active"
},
{
id: 2,
code: "S2",
status: "inactive"
},
{
id: 3,
code: "C1",
status: "active"
}
];
console.log(this.newObject(obj1, obj2));
Expected Output
[
{id:1, name: "Fruits",code:"G1", status:"active"},
{id:2, name: "TH",code:"S2", status:"inactive"},
{id:3, name: "city",code:"C1", status:"active"}
]
you can check this code
I fixed your object and you can find your expectation in the console
I am getting a result in my JavaScript file which I want to convert into another object.
My original result
[
{
"SName": "Set1",
"Elements": [
{
"Id": "3",
"Name": "Name1"
},
{
"Id": "5",
"Name": "Name2"
}
]
},
{
"SName": "Set2",
"Elements": [
{
"Id": "7",
"Name": "Name3"
},
{
"Id": "8",
"Name": "Name4"
}
]
}
]
Convert this to look like array of objects using jQuery or JavaScript. How can I achieve this?
[
{
"SName": "Set1",
"Id": 3,
"Name": "Name1"
},
{
"SName": "Set1",
"Id": 5,
"Name": "Name2"
},
{
"SName": "Set2",
"Id": 7,
"Name": "Name3"
},
{
"SName": "Set2",
"Id": 8,
"Name": "Name4"
}
]
var data = [
{
"SName": "Set1",
"Elements": [
{
"Id": "3",
"Name": "Name1"
},
{
"Id": "5",
"Name": "Name2"
}
]
},
{
"SName": "Set2",
"Elements": [
{
"Id": "7",
"Name": "Name3"
},
{
"Id": "8",
"Name": "Name4"
}
]
}
];
console.log(data);
var newData = data.reduce(function (newArray, currentSet) {
return newArray.concat(currentSet.Elements.map(function (element) {
return Object.assign( { SName: currentSet.SName }, element);
}));
}, []);
console.log(newData);
The key here is the reduce function. What we are doing is creating a brand new array, by looping through each value of the outer array. We continuously concatenate onto our new array with the values we map from the inner array.
You could iterate the array, the Elements and the properties and build a new object and push it to the result set.
var array = [{ "SName": "Set1", "Elements": [{ "Id": "3", "Name": "Name1" }, { "Id": "5", "Name": "Name2" }] }, { "SName": "Set2", "Elements": [{ "Id": "7", "Name": "Name3" }, { "Id": "8", "Name": "Name4" }] }],
result = [];
array.forEach(function (a) {
a.Elements.forEach(function (b) {
var o = { SName: a.SName };
Object.keys(b).forEach(function (k) {
o[k] = b[k];
});
result.push(o);
});
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES6
var array = [{ "SName": "Set1", "Elements": [{ "Id": "3", "Name": "Name1" }, { "Id": "5", "Name": "Name2" }] }, { "SName": "Set2", "Elements": [{ "Id": "7", "Name": "Name3" }, { "Id": "8", "Name": "Name4" }] }],
result = [];
array.forEach(a => a.Elements.forEach(b => result.push(Object.assign({ SName: a.SName }, b))));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can do this with reduce(), forEach() and Object.assign()
var data = [{
"SName": "Set1",
"Elements": [{
"Id": "3",
"Name": "Name1"
}, {
"Id": "5",
"Name": "Name2"
}]
}, {
"SName": "Set2",
"Elements": [{
"Id": "7",
"Name": "Name3"
}, {
"Id": "8",
"Name": "Name4"
}]
}]
var result = data.reduce(function(r, e) {
e.Elements.forEach(function(o) {
r.push(Object.assign({SName: e.SName}, o))
})
return r;
}, [])
console.log(result)
Here is solution using jQuery, here is jsfiddle:
https://jsfiddle.net/noitse/3uk9qjnf/
I hope you know all key names so it wont be problem to do it fixed.
var json = [
{
"SName": "Set1",
"Elements": [
{
"Id": "3",
"Name": "Name1"
},
{
"Id": "5",
"Name": "Name2"
}
]
},
{
"SName": "Set2",
"Elements": [
{
"Id": "7",
"Name": "Name3"
},
{
"Id": "8",
"Name": "Name4"
}
]
}
]
var newJSON = []
$(json).each(function(index,value){
$(value.Elements).each(function(index1,value1){
newJSON.push({"SName":value.SName,"Id":value1.Id,"Name":value1.Name})
})
})
alert(JSON.stringify(newJSON))
Here is code , what it does it loops through first JSON , then loops through its elements , then it push it to new array
You could use the $.extend method, which lets you create a copy of an object, while merging with another object.
var source = [] // Replace with the initalization of your source array
var destination = [];
for (var i = 0; i < source.length; i++) {
var node = source[i];
for (var j = 0; j < node.Elements.length; j++) {
var subNode = node.Elements[j];
newNode = $.extend(subNode, node);
delete newNode["Elements"];
destination.push(newNode);
}
}
You can run the code in this fiddle.