Paasing an object into an array of arrays - javascript

Have an object that needs to be pass inside the array of source using javascript,throwing an error spec is undefined when using push function. will push function work for this scenario
var a = [
"name": "ben",
"type": "male",
"appType": "human",
"spec": {
"view": "instanceview",
"sink": {
"source": [{
"data": {
"path": "google/path",
"name": "test",
"Id": "11234",
},
"ref": "www.xyz.com",
"id": "isdfjsbfjsfb",
"resourceType": "app"
}
],
},
},
}]
var b = {
"data": {
"path": "google/path",
"name": "goldengate",
"Id": "11234vndslknvlsmnv",
},
"ref": "www.xyz.com",
"id": "6452367e5375",
"resourceType": "app"
}
a.spec.sink.source.push(b);
would expect b to be pushed to source

An array with string keys is not a valid structure, you need to convert a to an object
var a = { // <-- here
"name": "ben",
"type": "male",
"appType": "human",
"spec": {
"view": "instanceview",
"sink": {
"source": [
{
"data": {
"path": "google/path",
"name": "test",
"Id": "11234",
},
"ref": "www.xyz.com",
"id": "isdfjsbfjsfb",
"resourceType": "app"
}
],
},
},
} // <-- here

Related

how to update a deeply nested object in Javascript?

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)

Normalizr: normalize deep nested items

I have an array of data like this one
[
{
"id": "root_01",
"parents": [
{
"id": "parent_1",
"childrens": [
{
"id": "child_01",
"name": "ABC",
"group": "group_a"
},
{
"id": "child_02",
"name": "BBC",
"group": "group_b"
}
]
},
{
"id": "parent_2",
"childrens": [
{
"id": "child_03",
"name": "CCD",
"group": "group_a"
},
{
"id": "child_04",
"name": "EEF",
"group": "group_c"
}
]
}
]
},
{} // same as previous
]
and I'm trying to get rid of all parents data & catch & merge only child items like this one:
[
{
"id": "child_01",
"name": "ABC",
"group": "group_a"
},
{
"id": "child_02",
"name": "BBC",
"group": "group_b"
},
{
"id": "child_03",
"name": "CCD",
"group": "group_a"
},
{
"id": "child_04",
"name": "EEF",
"group": "group_c"
}
]
but after reading normalizr documentation I'm a little bit confused because I couldn't find this kind of example, so can anyone suggest me is it possible to make with normalizr or any better idea?
Thanks
Recusrion is what you need here:
const arr = [ { "id": "root_01", "parents": [ { "id": "parent_1", "childrens": [ { "id": "child_01", "name": "ABC", "group": "group_a" }, { "id": "child_02", "name": "BBC", "group": "group_b" } ] }, { "id": "parent_2", "childrens": [ { "id": "child_03", "name": "CCD", "group": "group_a" }, { "id": "child_04", "name": "EEF", "group": "group_c" } ] } ] }];
const flatten = arr => arr.flatMap(o=>o.parents ? flatten(o.parents) : o.childrens ? flatten(o.childrens) : o);
console.log(flatten(arr));

Convert nested JSON to flat JSON - In order to insert them as records in SQL

I have a JSON string in nested pattern like below:
NESTED (Just Example):
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}
I want an option or way to convert this nested JSON string to a flat JSON string so that I can insert them like a record in SQL table.
Can you please help on how to structure the JSON from nested to flat?

Nested Loops in angularjs

I have been using nested loops to access data of the json object to display the id and type of topping, however its not working. Here's my code:
var j_obj = {
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters": {
"batter": [{
"id": "1001",
"type": "Regular"
}, {
"id": "1002",
"type": "Chocolate"
}, {
"id": "1003",
"type": "Blueberry"
}, {
"id": "1004",
"type": "Devil's Food"
}]
},
"topping": [{
"id": "5001",
"type": "None"
}, {
"id": "5002",
"type": "Glazed"
}, {
"id": "5005",
"type": "Sugar"
}, {
"id": "5007",
"type": "Powdered Sugar"
}, {
"id": "5006",
"type": "Chocolate with Sprinkles"
}, {
"id": "5003",
"type": "Chocolate"
}, {
"id": "5004",
"type": "Maple"
}]
}
var Outer_log=[];
debugger
angular.forEach(j_obj, function(an_object){
//Outer_log.push("ID : "+an_object.id+" type : "+an_object.type);
angular.forEach(an_object.topping,function(innerobject){
Outer_log.push("ID : "+innerobject.id+" type : "+innerobject.type);
},Outer_log);
});
console.log(Outer_log);
Could someone please highlight the error in above code, Thanks
Without using nested loop you can iterate using angular.forEach like this
var finalArray=[];
angular.forEach(j_obj[0].topping, function(eachobject){
finalArray.push("ID : "+ eachobject.id+" type : "+ eachobject.type);
});
Angulars forEach is intended to iterate over arrays not object. so if you change your code to something like this
var j_obj = [{ ...}] //object is wrapped inside array.
it will work. Another thing is you don't need a nested loop in this case. You can just do:
angular.forEach(j_obj.topping, function(key, value){ ... });
you are iterating over object where as loop run over array.
hope this helps JSfiddle link
var j_obj = [{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"batters": {
"batter": [{
"id": "1001",
"type": "Regular"
}, {
"id": "1002",
"type": "Chocolate"
}, {
"id": "1003",
"type": "Blueberry"
}, {
"id": "1004",
"type": "Devil's Food"
}]
},
"topping": [{
"id": "5001",
"type": "None"
}, {
"id": "5002",
"type": "Glazed"
}, {
"id": "5005",
"type": "Sugar"
}, {
"id": "5007",
"type": "Powdered Sugar"
}, {
"id": "5006",
"type": "Chocolate with Sprinkles"
}, {
"id": "5003",
"type": "Chocolate"
}, {
"id": "5004",
"type": "Maple"
}]
}]
var Outer_log = [];
angular.forEach(j_obj, function(an_object) {
//Outer_log.push("ID : "+an_object.id+" type : "+an_object.type);
angular.forEach(an_object.topping, function(innerobject) {
Outer_log.push("ID : " + innerobject.id + " type : " + innerobject.type);
}, Outer_log);
});
console.log(Outer_log);

Appending a key value at root node and all its children in JSON

This is the JSON Object i am working on :
var r={
"id": "A",
"name": "Analysis",
"url": "A.html",
"root": true,
"children": [
{
"id": "B",
"name": "Introduction",
"url": "B.html",
"root": true,
"children": [{
"id": "C",
"name": "Creating",
"url": "c.html#I1"
}, {
"id": "D",
"name": "Running",
"url": "d.html#I2"
}]
},
{
"id": "E",
"name": "Transient Analysis",
"url": "E.html",
"root": true,
"children": [{
"id": "F",
"name": "RC",
"url": "F.html#T1"
}, {
"id": "G",
"name": "RLC",
"url": "G.html#T2"
}]
}
]
}
I want this as another key-value
path="home.html"
and it should be appended not only to the root node but to all its children node.
So it should look like.
var r= {
"id": "A",
"name": "Analysis",
"url": "A.html",
"path":"home.html",
"root": true,
"children": [
{
"id": "B",
"name": "Introduction",
"url": "B.html",
"root": true,
"path":"home.html",
"children": [{
"id": "C",
"name": "Creating",
"url": "c.html#I1",
"path":"home.html"
}, {
"id": "D",
"name": "Running",
"url": "d.html#I2",
"path":"home.html"
}]
},
{
"id": "E",
"name": "Transient Analysis",
"url": "E.html",
"root": true,
"path":"home.html",
"children": [{
"id": "F",
"name": "RC",
"url": "F.html#T1",
"path":"home.html"
}, {
"id": "G",
"name": "RLC",
"url": "G.html#T2",
"path":"home.html"
} ]
}
]
}
so far I've tried is this :
r.path={"home.html"}
and
var to_concatjson = JSON.parse(r);
to_concatjson["path"] = {"home.html"};
but both are not working for me.
Further Modifications in the above question :
Lets say i am loading my json content from my File 1
File 1 looks like
[
{
"id":"a", "name":"a","children":[
{ "id":"b", "name":"b","children":[
{ "id":"b", "name":"b"},
{ "id":"c", "name":"c"},
{ "id":"d", "name":"d"}
]
},
{ "id":"e", "name":"e","children":[
{ "id":"f", "name":"f"},
{ "id":"g", "name":"g"},
{ "id":"h", "name":"h"}
]
},
]
}
]
the content of my json file is loaded in result[0]. and when i am calling addPath like :
result[0]=addPath(result[0]);
it shows me an error that "forEach" will not work as it is not the property of object.
Do it with this code :-
function addPath(obj){
if(!obj.hasOwnProperty('path')){
obj.path = 'home.html';
}
if(obj.hasOwnProperty('children')){
obj.children.forEach(function(obj1){
obj1 = addPath(obj1);
});
}
return obj;
}
r = addPath(r);
I know that my way is not optimum, but it is working:
I append new item through .replace(...) (without loop)
var r = JSON.parse(JSON.stringify(r).replace(new RegExp("\"url\"", 'g'), '"path": "home.html", "url"'));
console.log(r);
var r={
"id": "A",
"name": "Analysis",
"url": "A.html",
"root": true,
"children": [
{
"id": "B",
"name": "Introduction",
"url": "B.html",
"root": true,
"children": [{
"id": "C",
"name": "Creating",
"url": "c.html#I1"
}, {
"id": "D",
"name": "Running",
"url": "d.html#I2"
}]
},
{
"id": "E",
"name": "Transient Analysis",
"url": "E.html",
"root": true,
"children": [{
"id": "F",
"name": "RC",
"url": "F.html#T1"
}, {
"id": "G",
"name": "RLC",
"url": "G.html#T2"
}]
}
]
}
var r = JSON.parse(JSON.stringify(r).replace(new RegExp("\"url\"", 'g'), '"path": "home.html", "url"'));
console.log(r);

Categories