frame array of recursive json object from an another array of objects - javascript

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);

Related

Restructure Nested JSON Data And Removing Some Keys

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!

Nested for loop issue in JavaScript

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)

Javascript - Recursive object manipulation

I'm having some difficulties with recursive functions. Can someone help me?
I have the following structure:
{
"entity": {
"entityLabel": "Virtual Reality",
"parent": [
{
"entity": {
"entityLabel": "Artificial Intelligence",
"parent": [
{
"entity": {
"entityLabel": "Information Technology"
}
}
]
}
}
]
}
}
And I need the following result:
{
"label": "Information Technology",
"children": [
{
"label": "Artificial Intelligence"
"children": [
{
label: "Virtual Reality"
}
]
}
]
}
I couldn't accomplish the reverse order. My current code is:
const termTree = term => {
const label = term.entity?.entityLabel
const parentArr = term.entity?.parent
const obj = {}
let children = []
if (parentArr) {
children = parentArr.map(item => {
return termTree(item)
})
}
obj.label = label
if (!empty(children)) obj.children = children
return obj
}
Which results in the same order but with different labels:
{
"label": "Virtual Reality",
"children": [
{
"label": "Artificial Intelligence",
"children": [
{
"label": "Information Technology"
}
]
}
]
}
As you can see it's reverse and it's not just a matter of changing labels.
Thanks
You could take an iterative and recursive approach by handing over a source array for the new label and a target array for the final result with children.
By taking the above wanted format, without a children property in the most inner object, this approach take as target an object with a children. The reducing part for generating the new data structure takes only objects as return value and creates children if necessary.
var data = { entity: { entityLabel: "Virtual Reality", parent: [{ entity: { entityLabel: "Artificial Intelligence", parent: [{ entity: { entityLabel: "Information Technology" } }] } }] } },
result = [];
[data].forEach(function iter(source, target) {
return function ({ entity: { entityLabel, parent } }) {
source = [entityLabel, ...source];
if (parent) return parent.forEach(iter(source, target));
source.reduce((t, label) => {
var temp = (t.children = t.children || []).find(o => o.label === label);
if (!temp) {
t.children.push(temp = { label });
}
return temp;
}, target);
}
}([], { children: result }));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Create a JSON reading recursively from another unknown JSON with Javascript

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));
}

Convert JSON from one format to other

I'm trying to convert the below JSON to another format wherein the reultant JSON dosen't contain valueChainEntity object name and also I want to delete the inputs and outputs array.Note that the structure is a parent child relation and the inputs and outputs array can be present inside the items array at any level.Even in the all levels(but only inside items array)
var inputJSON = [
{
"valueChainEntity":{
"id":308,
"valueChainEntityId":48,
"items":[
{
"valueChainEntity":{
"id":309,
"valueChainEntityId":49,
"items":[
{
"valueChainEntity":{
"id":312,
"valueChainEntityId":50,
"items":[
]
},
"inputs":[
{
"id":312,
"valueChainEntityId":50,
"items":[
]
}
],
"outputs":[
{
"id":313,
"valueChainEntityId":50
}
]
}
]
}
}
]
}
}
]
var outputJSON= [
{
"id":308,
"valueChainEntityId":48,
"items":[
{
"id":309,
"valueChainEntityId":49,
"items":[
{
"id":312,
"valueChainEntityId":50,
"items":[
]
}
]
}
]
}
]
My code:
inputJSON.forEach((item) => {
return item.valueChainEntity;
});
//which will traverse only through the first level and will not delete the **inputs** and **outputs** array..
See if following works:
function parseInputJSON(inp) {
return inp.map(function (item) {
return getValueChainEntity(item);
});
}
function getValueChainEntity(item) {
if (item['valueChainEntity'] != undefined) {
var valueChainEntity = item.valueChainEntity;
valueChainEntity.items = parseInputJSON(valueChainEntity.items);
return valueChainEntity;
}
return item;
}
var inputJSON=[
{
"valueChainEntity": {
"id": 308,
"valueChainEntityId": 48,
"items": [
{
"valueChainEntity": {
"id": 309,
"valueChainEntityId": 49,
"items": [
{
"valueChainEntity": {
"id": 312,
"valueChainEntityId": 50,
"items": []
},
"inputs": [
{
"id": 312,
"valueChainEntityId": 50,
"items": []
}
],
"outputs": [
{
"id": 313,
"valueChainEntityId": 50
}
]
}
]
}
}
]
}
}];
var newInput = parseInputJSON(inputJSON);
document.getElementById("json").innerHTML = JSON.stringify(newInput, undefined, 4);
<pre id="json"></pre>
Here's another way that is working..
Sample code
function populateChildrenRecursively(outputTypeId, valueChainEntities, parentValueChainEntity) {
for (var i = 0; i < valueChainEntities.length; i++) {
if (valueChainEntities[i].valueChainEntity.valueChainEntityId != parentValueChainEntity.valueChainEntity.valueChainEntityId && hasInput(outputTypeId, valueChainEntities[i].inputs)) {
parentValueChainEntity.valueChainEntity.items.push(valueChainEntities[i]);
if (valueChainEntities[i].outputs.length > 0) {
valueChainEntities[i].valueChainEntity.items = [];
for (var j = 0; j < valueChainEntities[i].outputs.length; j++) {
populateChildrenRecursively(valueChainEntities[i].outputs[j].outputTypeId, valueChainEntities, valueChainEntities[i]);
}
}
}
}
}
https://plnkr.co/edit/d2wtXcaU37quthBjgrCu?p=preview

Categories