Input JSON:
{
"parent":[
{
"parentId":"111",
"children":[
{
"child":"child1",
"childName":"ABCDE"
},
{
"childSchool":"XYZ School",
"childClass":"fourth"
}
]
},
{
"parentId":"222",
"children":[
{
"child":"child1",
"childName":"FGHI"
},
{
"childSchool":"XYZ School",
"childClass":"fourth"
}
]
},
{
"parentId":"333",
"children":[
{
"child":"child1",
"childName":"BBB"
},
{
"childSchool":"XYZ School",
"childClass":"fifth"
}
]
}
]
}
Using JavaScript i need following output. I tried to loop through parent array using 2 for loop (i and i+1), and compare the childSchool field , if it is same then append childName as 1 string as shown in output(ABC*, FGH*) and the item not matching will be separate array. But this solution is not working. Can someone help?
OutPut:
{
"parent":[
{
"parentId":"111",
"children":[
{
"child":"child1",
"childName":"ABC*, FGH*" // <==== expected output
},
{
"childSchool":"XYZ School",
"childClass":"fourth"
}
]
},
{
"parentId":"333",
"children":[
{
"child":"child1",
"childName":"BBB"
},
{
"childSchool":"XYZ School",
"childClass":"fifth"
}
]
}
]
}
for(let i=0; i<parent.length; i++) {
for(let j=i+1; j<parent.length; j++) {
for(let child of parent[i].children) {
for(let chd of parent[j].children) {
if(child.childSchool === 'XYZ School' && chd.childSchool === 'XYZ School' && child.childClass === 'fourth && chd.childClass === 'fourth') {
sameSchoolGrade = true;
childName=child.childName + ',' + chd.childName;
}
}
if(sameSchoolGrade) {
//trying to assign to response obj
}
}
}}
it's a strange Json, generally the arrays should be the same properties,
You can get it in two pass, first a loop over the array search is there're a node with the conditions, after filter the data.
this.data.parent.forEach(x=>{
//try to find a node with same childSchool and childClass
//see that childSchool and childClass is under children[1].childSchool and children[1].ChildClass
const node=this.data.parent.find(i=>i.children[1].childSchool==x.children[1].childSchool &&
i.children[1].childClass==x.children[1].childClass)
//if it's not the same
if (node!=x)
{
//add to childName the childName
node.children[0].childName+=","+x.children[0].childName
//equal the childName to ""
x.children[0].childName="";
}
})
//filter and get only the childName has a value
this.data.parent=this.data.parent.filter(x=>x.children[0].childName)
Related
I need to restructure a nested JSON data.
Here is how it looks like:
{
"MainKey1": [
{
"Section1": {
"ParentTag1 Mapped Label": {
"ParentTag1": {
"Tag1 Mapped Label": {
"Tag1": "1234567890"
}
}
}
}
},
{
"Section2": {
"ParentTag1 Mapped Label": {
"ParentTag1": {
"Tag1 Label": {
"Tag1": "111222333444"
},
"Tag2 Label": {
"Tag2": "121212"
},
"Tag3 Label": {
"Tag3": "0987654321"
}
}
}
}
}
],
"MainKey2": [
{
"Section1": {
"ParentTag1 Mapped Label": {
"ParentTag1": {
"Tag1 Mapped Label": {
"Tag1": "1234567890"
}
}
}
}
}
]
}
And this is a sample of the converted JSON:
{
MainKey: [
{
Section1: [
{
ParentTag1: [
{ Tag1: "1234567890" }
]
}
]
},
{
Section2: [
{
ParentTag1: [
{ Tag1: "111222333444" },
{ Tag2: "121212" },
{ Tag3: "0987654321" }
]
}
]
}
],
MainKey2: [
{
Section1: [
{
ParentTag1 : [
{ Tag1: "1234567890" }
]
}
]
}
]
}
Rules:
Everything inside a MainKey (outermost keys, could be any name) should be an array
All labels should be stripped (as the label could be any name, without the actual word "Label", we can determine if it is a label based on the depth level. Since the JSON will have the label as the parent and the actual "tag" as a child.
Here is what I currently have (it is a mess, sorry!)
function convertJson (jsonObj) {
const mainKeys = Object.keys(jsonObj)
let output = {}
for (let i = 0; i < mainKeys.length; i++) {
const mainKey = mainKeys[i]
let result = []
output[mainKey] = result
for (let j = 0; j < jsonObj[mainKey].length; j++) {
const innerObj = {...jsonObj[mainKey][j]}
const sectionName = Object.keys(innerObj)[0]
const sectionObj = {}
sectionObj[sectionName] = []
const index = result.push(sectionObj) - 1
parseObj(innerObj[sectionName], result[index], 0) // if I change 2nd param to: result, it generates incorrect output
}
}
console.log(output)
}
function parseObj (innerObj, result, depthCount) {
for (var key in innerObj) {
if (typeof innerObj[key] === "object") {
if (depthCount % 2 === 1) {
const parentObj = {}
parentObj[key] = []
result.push(parentObj)
depthCount++
parseObj(innerObj[key], parentObj[key], depthCount)
} else {
depthCount++
parseObj(innerObj[key], result, depthCount)
}
} else {
const keyValuePairObj = {}
keyValuePairObj[key] = innerObj[key]
result.push(keyValuePairObj)
}
}
return result
}
convertJson(json)
But it generates an error:
Uncaught TypeError: result.push is not a function
Now if I change line 90 from:
parseObj(innerObj[sectionName], result[index], 0)
to:
parseObj(innerObj[sectionName], result, 0)
Here is incorrect output:
{
"MainKey1": [
{
"Section1": []
},
{
"ParentTag1": [
{
"Tag1": "1234567890"
}
]
},
{
"Section2": []
},
{
"ParentTag1": [
{
"Tag1": "111222333444"
},
{
"Tag2 Label": [
{
"Tag2": "121212"
}
]
},
{
"Tag3": "0987654321"
}
]
}
],
"MainKey2": [
{
"Section1": []
},
{
"Tag1": "1234567890"
}
]
}
And here is my fiddle:
https://jsfiddle.net/kzaiwo/L4avxmyd/36/
Thanks a lot! Appreciate any help!
i have an array of objects of the below format
each with a unique 'sub-task' entry, each of this sub-task is to be embedded as a children element of each unique 'task' from the 'tasks' array
[
{
"sub-task":"abc",
"task":"alpha1"},
{
"sub-task":"def",
"task":"alpha1"},
{
"sub-task":"ijkl",
"task":"proto"},
{
"sub-task":"mno",
"task":"def"},
{
"sub-task":"qrs",
"task":"proto"},
{
"sub-task":"asdf",
"task":"mno"},
]
i was trying to frame an another array of below format
[
{
"name":"alpha1",
"children":[
{
"name":"abc"
},
{
"name":"def",
"children":[
{
"name":"mno"
}
]
}
]
},
{
"name":"proto",
"children":[
{
"name":"ijkl"
},
{
"name":"qrs",
"children":[
{
"name":"asdf"
}
]
}
]
}
]
i was trying of below logic, but ended up with no solution...
var treeData = [];
for( var ele of tasks){
recurOn(treeData,ele);
}
function recurOn(arr,obj){
if(arr.length == 0){
treeData.push({name:obj.parentGroup,children:[{name:obj.groupName}]})
//console.log(treeData);
return 1;
}else {
for(var item of treeData){
if(item.name == obj.parentGroup){
//console.log('item: ', item);
item.children.push({name:obj.groupName});
break;
}
else {
treeData.push(recurOn([],obj))
}
}
return 1;
}
}
//console.log(treeData);
//console.log(result);
Since the no of levels an elements holds is not known i was unable to fix for a logic
Use a map to store object reference.
let input = [
{ "sub-task": "abc", "task": "alpha1" },
{ "sub-task": "def", "task": "alpha1" },
{ "sub-task": "ijkl", "task": "proto" },
{ "sub-task": "mno", "task": "def" },
{ "sub-task": "qrs", "task": "proto" },
{ "sub-task": "asdf", "task": "mno" },
];
let map = new Map, result = [];
input.forEach(({ ["sub-task"]: name, task }) => {
let node = map.get(task), child = { name, children: [] };
if (!node) {
map.set(task, node = { name: task, children: [] });
result.push(node);
}
map.set(name, child);
node.children.push(child);
})
console.log(result);
I've been trying to figure out a way of doing this. This is my object:
{
"id":1,
"name":"Blooper Corp.",
"emoji":"π",
"parent_id":null,
"children":[
{
"id":2,
"name":"Food",
"emoji":"π₯©",
"parent_id":1,
"children":[
]
},
{
"id":3,
"name":"Canine Therapy",
"emoji":"π",
"parent_id":1,
"children":[
{
"id":4,
"name":"Massages",
"emoji":"π",
"parent_id":3,
"children":[
]
},
{
"id":5,
"name":"Games",
"emoji":"πΎ",
"parent_id":3,
"children":[
]
}
]
}
]
}
I'm trying to get the last id of the array so I can use it in the new child array and add it as a child to that specific tier, for example:
{
"id":6, // New id
"name":"Music",
"emoji":"",
"parent_id":4, //this will be the parent id it belongs to
"children":[
]
}
This is my javascript button function:
function askUserForTeamDetails( team ) {
const emoji = prompt( 'Enter new teamβs emoji:' );
if ( null === emoji ) {
return;
}
const name = prompt( 'Enter new teamβs name:' );
if ( null === name ) {
return;
}
let tree = getTree();
tree.id = {}; //new child array to push depending on parent id
return { name, emoji };
}
getTree():
const tree = {"id":1,"name":"Rusty Corp.","emoji":"π","parent_id":null,"children":[{"id":2,"name":"Food","emoji":"π₯©","parent_id":1,"children":[]},{"id":3,"name":"Canine Therapy","emoji":"π","parent_id":1,"children":[{"id":4,"name":"Massages","emoji":"π","parent_id":3,"children":[]},{"id":5,"name":"Games","emoji":"πΎ","parent_id":3,"children":[]}]}]};
return tree;
I've tried using Object.keys(tree)[Object.keys(tree).length-1]; But I don't see how this will work since it's multidimensional.
I hope someone can advise a way of doing this.
Thanks
If you want to add new object based on parent_id property that can be on any level, you can create recursive function that will traverse the object with for...in loop and push the object to children if the id matches.
const data = {"id":1,"name":"Blooper Corp.","emoji":"π","parent_id":null,"children":[{"id":2,"name":"Food","emoji":"π₯©","parent_id":1,"children":[]},{"id":3,"name":"Canine Therapy","emoji":"π","parent_id":1,"children":[{"id":4,"name":"Massages","emoji":"π","parent_id":3,"children":[]},{"id":5,"name":"Games","emoji":"πΎ","parent_id":3,"children":[]}]}]}
function insert(data, obj, pid = null) {
if (pid == obj.parent_id) {
data.children.push(obj);
return;
}
if (data.children) {
data.children.forEach(e => insert(e, obj, e.id))
}
}
function getLastId(data) {
let result = null;
function search(data) {
if (!result || data.id > result) result = data.id;
if (data.children) data.children.forEach(search);
}
search(data);
return result;
}
const newObj = {
"id": getLastId(data) + 1,
"name": "Music",
"emoji": "",
"parent_id": 4,
"children": []
}
insert(data, newObj);
console.log(data)
You could write a recursive function that would loop over each of the children until the id was found. One way of doing this could be:
function findTeamById(id, tree) {
if (id === tree.id) return tree //returning tree as it is the current team's object
for (let i = 0; i < tree.length; i++) {
let teamTree = findTeamById(id, tree[i])
if (teamTree !== false) {
// return the found tree
return teamTree
}
}
// if no tree was found return false
return false
}
// EDIT: forgot to show how to add the child
const newTeam = {
"id":6, // New id
"name":"Music",
"emoji":"",
"parent_id":4, //this will be the parent id it belongs to
"children":[
]
}
// this will push the new team to the childrens array of the newTeams parent
findTeamById(newTeam.parent_id, myTree).children.push(newTeam)
It seems like you'll need a recursive function to find the max ID, then get the parent of that maxID object and put the new object in its children.
const tree = {"id":1,"name":"Rusty Corp.","emoji":"π","parent_id":null,"children":[{"id":2,"name":"Food","emoji":"π₯©","parent_id":1,"children":[]},{"id":3,"name":"Canine Therapy","emoji":"π","parent_id":1,"children":[{"id":4,"name":"Massages","emoji":"π","parent_id":3,"children":[]},{"id":5,"name":"Games","emoji":"πΎ","parent_id":3,"children":[]}]}]};
const newObj = {
"id": 6,
"name": "Music",
"emoji": "",
"parent_id": 0,
"children": []
}
var maxID=0;
var parentObj = null;
function findMaxIDArray(obj) {
var tmpid = maxID;
maxID = Math.max(obj.id, maxID);
if (maxID>tmpid) {
parentObj = obj;
}
if (obj.children) {
for(let c=0;c<obj.children.length;c++){
if (obj.children[c]) {
findMaxIDArray(obj.children[c]);
}
}
}
}
findMaxIDArray(tree);
if (parentObj) {
newObj.parent_id=parentObj.id;
parentObj.children.push(newObj);
}
console.log(tree);
I have the below object and if I send some array I need the parents of those object.
Lets say if I send {Id:113} , It should return [11,1]
[
{
Id:1,
Name:"Test",
children:[
{
Id:11,
Name:"Test",
children:[
{
Id:113,
Name:"Test",
children:[
]
},
{
Id:114,
Name:"Test",
children:[
]
}
]
},
{
Id:12,
Name:"Test",
children:[
]
},
{
Id:13,
Name:"Test",
children:[
{
Id:115,
Name:"Test",
children:[
{
Id:1111,
Name:"Test",
children:[
]
}
]
}
]
},
{
Id:14,
Name:"Test",
children:[
]
}
]
} {
Id:2,
Name:"Test",
children:[
]
}
]
I am able to fetch each children item by using the below code.
this.selectedOMStructure = function (structure, id) {
_.each(structure, function (_item) {
if (_item.Id == id) {
_item.isChecked = !_item.isChecked;
if (_item.children) {
_this.checkAllChildren(_item.children, _item.isChecked);
} else {
return;
}
} else if (_item.children) {
_this.selectedOMStructure(_item.children, id);
}
})
}
this.checkAllChildren = function (structure, value) {
_.each(structure, function (_item) {
_item.isChecked = value;
if (_item.children) {
_this.checkAllChildren(_item.children, value);
} else {
return;
}
})
}
But I have no idea how to find the parents of mentioned ID
I am not sure if this is a better approach. Try this,
data will be having your array. main() is the entry point. And the value will be stored in a.
var a = [];
function main() {
a = [];
for (let i = 0; i < data.length; i++) {
checkChildren(data[i], 1111);
}
console.log(a);
}
function checkChildren(node, id) {
if (node.Id == id) {
return id;
}
else if (node.children) {
for (let i = 0; i < node.children.length; i++) {
let r = checkChildren(node.children[i], id);
if (r != 0) {
a.push(node.Id);
return node.Id;
}
}
return 0;
}
}
main();
You will need to map the values from this data structure into a new data structure.
Consider using a recursive algorithm that attaches a new parent field to every item while also adding it to a map from id to the item.
I'd like to read recursively all nodes from a generic JSON (so I'm not asking for a script that handles exclusively this kind of structure) and while reading I would to create another JSON in a structure like this (the example is just an excerpt):
[
{
"name":"AgreementOffer",
"size":20000000,
"children":[
{
"name":"Name",
"size":2000000,
"children":[
{
"name":"1cap",
"size":90
}
]
},
{
"name":"Context",
"size":2000000,
"children":[
{
"name":"AgreementInitiator",
"size":200,
"children":[
{
"name":"$SPECS-CUSTOMER",
"size":100
}
]
},
{
"name":"AgreementInitiator",
"size":200,
"children":[
{
"name":"$SPECS-CUSTOMER",
"size":100
}
]
},
{
"name":"AgreementResponder",
"size":200,
"children":[
{
"name":"$SPECS-APPLICATION",
"size":100
}
]
},
{
"name":"AgreementResponder",
"size":200,
"children":[
{
"name":"$SPECS-APPLICATION",
"size":100
}
]
},
{
"name":"ServiceProvider",
"size":200,
"children":[
{
"name":"AgreementResponder",
"size":100
}
]
},
{
"name":"ServiceProvider",
"size":200,
"children":[
{
"name":"AgreementResponder",
"size":100
}
]
},
{
"name":"ExpirationTime",
"size":200,
"children":[
{
"name":"2014-02-02T06:00:00",
"size":100
}
]
},
{
"name":"ExpirationTime",
"size":200,
"children":[
{
"name":"2014-02-02T06:00:00",
"size":100
}
]
},
{
"name":"TemplateName",
"size":200,
"children":[
{
"name":"Y2-APP-TEMPLATE",
"size":100
}
]
},
{
"name":"TemplateName",
"size":200,
"children":[
{
"name":"Y2-APP-TEMPLATE",
"size":100
}
]
}
]
}
]
}
]
So, I ask you for a script be able to handle a generic JSON (unknown structure and deep) and create another JSON written with the above structure.
Thanks!
Try it at https://jsfiddle.net/zqkdq5mf/1/
function AppendObject(obj) {
//console.log(JSON.stringify(obj) + ":" + JSON.stringify(obj).length);
var Summary = null;
for (var propertyName in obj) {
if (typeof obj[propertyName] === "object" && !Summary) {
Summary = { name: propertyName.toString(), size: JSON.stringify(obj).length, children: [] };
for (var childPropertyName in obj[propertyName]) {
var Child = {};
Child[childPropertyName] = obj[propertyName][childPropertyName];
Summary.children[Summary.children.length] = AppendObject(Child);
}
break;
} else if (!Summary) Summary = { key: propertyName, value: obj[propertyName], size: JSON.stringify(obj).length };
}
return Summary;
}
function Convert() {
$(".data").empty();
var ParsedJSON = $.parseJSON($("textarea").val()),
ObjectArray = [],
Summaries = [];
if (!(ParsedJSON instanceof Array)) ObjectArray[0] = ParsedJSON;
else ObjectArray = ParsedJSON;
for (var i = 0; i < ObjectArray.length; i++) Summaries[Summaries.length] = AppendObject(ObjectArray[i]);
$(".data").text(JSON.stringify(Summaries));
}