Nested JSON, create new array with values from multiple levels? - javascript

I have this nested json object but I would like to construct a new one by taking elements of the original. I would like to make the second array below using the first, where the id key value becomes the key for a list of the emailAddress values in each permissionsOriginal:
[
{
"id": "1yKKftO0iOyvsacrW1mEr-tw43ttw3-8IorkDwiaYLgqI",
"name": "Doc Control",
"permissions": [
{
"emailAddress": "pkenny#cheese.co",
"role": "writer",
"displayName": "Bob Kenny"
},
{
"emailAddress": "nDrape#cheese.co",
"role": "writer",
"displayName": "Nute Drape"
}
]
},
{
"id": "149Lmt-g3w4w3efgh6thyherawer443awt3wrwa3rewrwa",
"name": "Untitled document",
"permissions": [
{
"emailAddress": "pkenny#cheese.co",
"role": "owner",
"displayName": "Bob Kenny"
}
]
},
{
"id": "egrs54h6w4hgwe5wegrgwegrhterwwrttre-Uffk8QRg4",
"name": "Documentation Control test",
"permissions": [
{
"emailAddress": "wDragon#cheese.co",
"role": "writer",
"displayName": "Grape Dragon"
},
{
"emailAddress": "pkenny#cheese.co",
"role": "owner",
"displayName": "Bob Kenny"
}
]
}
]
Second Snippet:
[
{
"1yKKftO0iOyvsacrW1mEr-tw43ttw3-8IorkDwiaYLgqI": [
"pkenny#cheese.co",
"nDrape#cheese.co"
]
},
{
"149Lmt-g3w4w3efgh6thyherawer443awt3wrwa3rewrwa": [
"pkenny#cheese.co"
]
},
{
"egrs54h6w4hgwe5wegrgwegrhterwwrttre-Uffk8QRg4": [
"wDragon#cheese.co",
"pkenny#cheese.co"
]
}
]

Loop through each element, then loop through permissions and extract the email.
let resp = [{
"id": "1yKKftO0iOyvsacrW1mEr-tw43ttw3-8IorkDwiaYLgqI",
"name": "Doc Control",
"permissions": [{
"emailAddress": "pkenny#cheese.co",
"role": "writer",
"displayName": "Bob Kenny"
},
{
"emailAddress": "nDrape#cheese.co",
"role": "writer",
"displayName": "Nute Drape"
}
]
},
{
"id": "149Lmt-g3w4w3efgh6thyherawer443awt3wrwa3rewrwa",
"name": "Untitled document",
"permissions": [{
"emailAddress": "pkenny#cheese.co",
"role": "owner",
"displayName": "Bob Kenny"
}]
},
{
"id": "egrs54h6w4hgwe5wegrgwegrhterwwrttre-Uffk8QRg4",
"name": "Documentation Control test",
"permissions": [{
"emailAddress": "wDragon#cheese.co",
"role": "writer",
"displayName": "Grape Dragon"
},
{
"emailAddress": "pkenny#cheese.co",
"role": "owner",
"displayName": "Bob Kenny"
}
]
}
]
let res = [];
resp.forEach((data) => {
let emailArray = [];
let resObj = {};
data.permissions.forEach((permData) => {
emailArray.push(permData['emailAddress']);
})
resObj[data.id] = emailArray;
res.push(resObj);
})
console.log(res);

Related

Extract the parent node name from Tree who has childrens

I want to iterate the tree and need to get the id of all the nodes which has the children in string array. while looping it is just returning me the record but doesn't extract the name of the node.
e.g const result = ['root', 'USER', 'ROLE', 'DASHBOARD', 'BRAND', 'COMPANY'];
{
"id": "root",
"name": "Roles and Permissions",
"children": [
{
"id": "USER",
"name": "USER",
"children": [
{
"id": "1",
"name": "VIEW"
},
{
"id": "2",
"name": "CREATE"
},
{
"id": "3",
"name": "EDIT"
}
]
},
{
"id": "ROLE",
"name": "ROLE",
"children": [
{
"id": "8",
"name": "VIEW"
},
{
"id": "9",
"name": "CREATE"
},
{
"id": "10",
"name": "EDIT"
},
{
"id": "11",
"name": "DELETE"
}
]
},
{
"id": "DASHBOARD",
"name": "DASHBOARD",
"children": [
{
"id": "BRAND",
"name": "BRAND",
"children": [
{
"id": "52",
"name": "VIEW"
},
{
"id": "53",
"name": "CREATE"
},
{
"id": "54",
"name": "EDIT"
},
{
"id": "55",
"name": "DELETE"
}
]
},
{
"id": "COMPANY",
"name": "COMPANY",
"children": [
{
"id": "56",
"name": "VIEW"
},
{
"id": "57",
"name": "CREATE"
},
{
"id": "58",
"name": "EDIT"
},
{
"id": "59",
"name": "DELETE"
}
]
}
]
}
]
}
I tried various looping method to get the list, e.g. but not returning the exact name of the node.
function getParent(nodes) {
if(Array.isArray(nodes.children)) {
return nodes.children.map((node) => getParent(node));
}
return nodes.name;
}
You can store the resp in an array and return that array.
const q = {
"id": "root",
"name": "Roles and Permissions",
"children": [
{
"id": "USER",
"name": "USER",
"children": [
{
"id": "1",
"name": "VIEW"
},
{
"id": "2",
"name": "CREATE"
},
{
"id": "3",
"name": "EDIT"
}
]
},
{
"id": "ROLE",
"name": "ROLE",
"children": [
{
"id": "8",
"name": "VIEW"
},
{
"id": "9",
"name": "CREATE"
},
{
"id": "10",
"name": "EDIT"
},
{
"id": "11",
"name": "DELETE"
}
]
},
{
"id": "DASHBOARD",
"name": "DASHBOARD",
"children": [
{
"id": "BRAND",
"name": "BRAND",
"children": [
{
"id": "52",
"name": "VIEW"
},
{
"id": "53",
"name": "CREATE"
},
{
"id": "54",
"name": "EDIT"
},
{
"id": "55",
"name": "DELETE"
}
]
},
{
"id": "COMPANY",
"name": "COMPANY",
"children": [
{
"id": "56",
"name": "VIEW"
},
{
"id": "57",
"name": "CREATE"
},
{
"id": "58",
"name": "EDIT"
},
{
"id": "59",
"name": "DELETE"
}
]
}
]
}
]
}
let result = []
function r(nodes){
if(Array.isArray(nodes.children)){
result.push(nodes.name);
nodes.children.map((c) => r(c))
return result;
}
return result;
}
console.log(r(q))
You can simply use a recursive function. Here ids is an array. You can initialize it before calling the function. Call this function in your getting IDs method.
const getIdFromNodesWithChild = (node) => {
if (node.children != undefined){
ids.push(node.id)
const children_list = node.children
children_list.forEach( new_child => getIdFromNodesWithChild(new_child))
}}
caller function
const returnIds = (tree) => {
ids = []
getIdFromNodesWithChild(tree)
return (ids)
}
result : ['root', 'USER', 'ROLE', 'DASHBOARD', 'BRAND', 'COMPANY']

JavaScript array filtering embedded object array

how to filter array embedded object array?
I use filter and some, but the result is not my though.
var data = [
{
"app": "mail",
"scenarios": [
{
"name": "",
"description": "plugin 1",
"contacts": [
{
"resourceId": "001",
"isPrimary": false
}
]
},
{
"name": "app2",
"description": "plugin 2",
"contacts": [
{
"resourceId": "002",
"isPrimary": false
}
]
}
]
},
{
"app": "mail2",
"scenarios": [
{
"name": "app1",
"description": "plugin 1",
"contacts": [
{
"resourceId": "001",
"isPrimary": false
}
]
},
{
"name": "app2",
"description": "plugin 2",
"contacts": [
{
"resourceId": "002",
"isPrimary": false
}
]
}
]
}
];
result = data.filter(app => app.scenarios.some(scenario => scenario.contacts.some(concact => concact.resourceId == '001')));
I want to filter the data to
[
{
"app": "mail",
"scenarios": [
{
"name": "",
"description": "plugin 1",
"contacts": [
{
"resourceId": "001",
"isPrimary": false
}
]
}
]
},
{
"app": "mail2",
"scenarios": [
{
"name": "app1",
"description": "plugin 1",
"contacts": [
{
"resourceId": "001",
"isPrimary": false
}
]
}
]
}
]
var data = [{"app":"mail","scenarios":[{"name":"","description":"plugin 1","contacts":[{"resourceId":"001","isPrimary":false}]},{"name":"app2","description":"plugin 2","contacts":[{"resourceId":"002","isPrimary":false}]}]},{"app":"mail2","scenarios":[{"name":"app1","description":"plugin 1","contacts":[{"resourceId":"001","isPrimary":false}]},{"name":"app2","description":"plugin 2","contacts":[{"resourceId":"002","isPrimary":false}]}]}];
result = data.filter(app => app.scenarios.some(scenario => scenario.contacts.some(concact => concact.resourceId == '001')));
console.log(result);
I think you need to filter the scenarios array and contacts array both. If you want to get a scenario which has at least one contact with resourceId === "001" you could do the following.
let data = [
{
"app": "mail",
"scenarios": [
{
"name": "",
"description": "plugin 1",
"contacts": [
{
"resourceId": "001",
"isPrimary": false
}
]
},
{
"name": "app2",
"description": "plugin 2",
"contacts": [
{
"resourceId": "002",
"isPrimary": false
}
]
}
]
},
{
"app": "mail2",
"scenarios": [
{
"name": "app1",
"description": "plugin 1",
"contacts": [
{
"resourceId": "001",
"isPrimary": false
}
]
},
{
"name": "app2",
"description": "plugin 2",
"contacts": [
{
"resourceId": "002",
"isPrimary": false
}
]
}
]
}
];
for(let item of data) {
item.scenarios = item.scenarios.filter(value => {
let validContacts = value.contacts.filter(contact => {
return contact.resourceId === "001";
})
return validContacts.length > 0;
})
}
console.log(data);
var data = [
{
"app": "mail",
"scenarios": [
{
"name": "",
"description": "plugin 1",
"contacts": [
{
"resourceId": "001",
"isPrimary": false
}
]
},
{
"name": "app2",
"description": "plugin 2",
"contacts": [
{
"resourceId": "002",
"isPrimary": false
}
]
}
]
},
{
"app": "mail2",
"scenarios": [
{
"name": "app1",
"description": "plugin 1",
"contacts": [
{
"resourceId": "001",
"isPrimary": false
}
]
},
{
"name": "app2",
"description": "plugin 2",
"contacts": [
{
"resourceId": "002",
"isPrimary": false
}
]
}
]
}
];
data.forEach(dat => {
dat.scenarios = dat.scenarios.find(da => da.contacts.find(x=>x.resourceId === "001"));
});
console.log(data)
You can go thru the code see if it fits what you're looking. An assumption made which contacts array will only have one element. Let me know if it's otherwise

Accessing data in an object and creating new object with filtered data

I am trying to search for specific nodes within an object and display a new object with the required data. There could be single or multiple fields in each composite type like displayed below.
This is the original object:
{
"section": "personal",
"fields": [
{
"type": "composite",
"name": "name",
"label": "Name",
"fields": [
{
"type": "text",
"name": "given",
"label": "First name",
"value": "Joe"
},
{
"type": "text",
"name": "family",
"label": "Last name",
"value": "Smith"
}
]
},
{
"type": "composite",
"name": "address",
"label": "Address",
"fields": [
{
"type": "text",
"name": "streetName",
"label": "Street Name",
"value": "1 High St"
},
{
"type": "text",
"name": "city",
"label": "City",
"value": "New York"
}
]
}
]
}
The resulting object should look like this:
{
name: {
given: "Joe",
family: "Smith",
},
address: {
streetName: "1 Hight St",
city: "New York"
}
}
EDIT*** Ideally, I'd like to figure out a way to use javascript methods (map/reduce/filter) and/or lodash to come up with an answer.
This is more an outline of what i've been looking at so far with built in methods.
var convertVals = function() {
var data = fields.fields;
var filter = data.filter(function(form) {
return form
})
.filter(function(form) {
return form.name && form.fields;
})
.map(function(form) {
return {form.name, [form.name.name]: form.name.value};
})
};
convertVals();
Thanks,
You can use Array.prototype.reduce() to iterate nested fields arrays. Set "name" property value of parent object as property name of object with value set to object set to "name" and "value" properties of objects within child "fields" array
var data = {
"section": "personal",
"fields": [
{
"type": "composite",
"name": "name",
"label": "Name",
"fields": [
{
"type": "text",
"name": "given",
"label": "First name",
"value": "Joe"
},
{
"type": "text",
"name": "family",
"label": "Last name",
"value": "Smith"
}
]
},
{
"type": "composite",
"name": "address",
"label": "Address",
"fields": [
{
"type": "text",
"name": "streetName",
"label": "Street Name",
"value": "1 High St"
},
{
"type": "text",
"name": "city",
"label": "City",
"value": "New York"
}
]
}
]
}
var res = data.fields.reduce((o, {name, fields}) =>
(o[name] = fields.reduce((curr, {name:key, value}) =>
(curr[key] = value, curr),{}), o), {});
console.log(res);
Well, here you go! Figured I might as well take a crack at it as no more questions were coming in.
var originalObject = {
"section": "personal",
"fields": [
{
"type": "composite",
"name": "name",
"label": "Name",
"fields": [
{
"type": "text",
"name": "given",
"label": "First name",
"value": "Joe"
},
{
"type": "text",
"name": "family",
"label": "Last name",
"value": "Smith"
}
]
},
{
"type": "composite",
"name": "address",
"label": "Address",
"fields": [
{
"type": "text",
"name": "streetName",
"label": "Street Name",
"value": "1 High St"
},
{
"type": "text",
"name": "city",
"label": "City",
"value": "New York"
}
]
}
]
};
function convertVals(obj){
var retObj = {};
for(var i=0;i<obj.fields.length;i++){
var tempObj={};
for(var j=0;j<obj.fields[i].fields.length;j++){
tempObj[obj.fields[i].fields[j].name] = obj.fields[i].fields[j].value;
}
retObj[obj.fields[i].name] = tempObj;
}
return retObj;
}
console.log(convertVals(originalObject));
/*
Should return:
{
name: {
given: "Joe",
family: "Smith",
},
address: {
streetName: "1 Hight St",
city: "New York"
}
}
*/
Here's a lodash solution that uses keyBy to assign the keys for each fields and mapValues to get the value for each field.
function getFields(data) {
return data.value || _(data.fields)
.keyBy('name')
.mapValues(getFields)
.value();
}
var data = {
"section": "personal",
"fields": [{
"type": "composite",
"name": "name",
"label": "Name",
"fields": [{
"type": "text",
"name": "given",
"label": "First name",
"value": "Joe"
},
{
"type": "text",
"name": "family",
"label": "Last name",
"value": "Smith"
}
]
},
{
"type": "composite",
"name": "address",
"label": "Address",
"fields": [{
"type": "text",
"name": "streetName",
"label": "Street Name",
"value": "1 High St"
},
{
"type": "text",
"name": "city",
"label": "City",
"value": "New York"
}
]
}
]
};
function getFields(data) {
return data.value || _(data.fields)
.keyBy('name')
.mapValues(getFields)
.value();
}
console.log(getFields(data));
body > div { min-height: 100%; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
There is a hidden implication in the solution above, if the value contains falsey values then it would dismiss this value instead and assume that there's a fields value. To solve this, we can use has to check if a value key exists and then perform the same operations that we did above.
function getFields(data) {
return _.has(data, 'value')? data.value:
_(data.fields)
.keyBy('name')
.mapValues(getFields)
.value();
}
var data = {
"section": "personal",
"fields": [{
"type": "composite",
"name": "name",
"label": "Name",
"fields": [{
"type": "text",
"name": "given",
"label": "First name",
"value": "Joe"
},
{
"type": "text",
"name": "family",
"label": "Last name",
"value": "Smith"
}
]
},
{
"type": "composite",
"name": "address",
"label": "Address",
"fields": [{
"type": "text",
"name": "streetName",
"label": "Street Name",
"value": "1 High St"
},
{
"type": "text",
"name": "city",
"label": "City",
"value": "New York"
}
]
}
]
};
function getFields(data) {
return _.has(data, 'value')? data.value:
_(data.fields)
.keyBy('name')
.mapValues(getFields)
.value();
}
console.log(getFields(data));
body > div { min-height: 100%; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

How can I access specific value of JSON object? [duplicate]

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 6 years ago.
I can't seem to console.log the item name and just that. It's in the position data -> pricing -> tables -> items -> name. I am going for an output that says "Toy Panda".
[
{
"event": "recipient_completed",
"data": {
"id": "msFYActMfJHqNTKH8YSvF1",
"name": "Sample Document",
"status": "document.draft",
"date_created": "2014-10-06T08:42:13.836022Z",
"date_modified": "2016-03-04T02:21:13.963750Z",
"action_date": "2016-09-02T22:26:52.227554",
"action_by": {
"id": "FyXaS4SlT2FY7uLPqKD9f2",
"email": "john#appleseed.com",
"first_name": "John",
"last_name": "Appleseed"
},
"created_by": {
"id": "FyXaS4SlT2FY7uLPqKD9f2",
"email": "john#appleseed.com",
"first_name": "John",
"last_name": "Appleseed",
"avatar": "https://pd-live-media.s3.amazonaws.com/users/FyXaS4SlT2FY7uLPqKD9f2/avatar.jpg"
},
"recipients": [
{
"id": "FyXaS4SlT2FY7uLPqKD9f2",
"email": "john#appleseed.com",
"first_name": "John",
"last_name": "Appleseed",
"role": "signer",
"recipient_type": "Signer",
"has_completed": true
}
],
"sent_by": {
"id": "FyXaS4SlT2FY7uLPqKD9f2",
"email": "john#appleseed.com",
"first_name": "John",
"last_name": "Appleseed",
"avatar": "https://pd-live-media.s3.amazonaws.com/users/FyXaS4SlT2FY7uLPqKD9f2/avatar.jpg"
},
"metadata": {
"salesforce_opp_id": "123456",
"my_favorite_pet": "Panda"
},
"tokens": [
{
"name": "Favorite Animal",
"value": "Panda"
}
],
"fields": [
{
"uuid": "YcLBNUKcx45UFxAK3NjLIH",
"name": "Textfield",
"title": "Favorite Animal",
"value": "Panda",
"assigned_to": {
"id": "FyXaS4SlT2FY7uLPqKD9f2",
"email": "john#appleseed.com",
"first_name": "John",
"last_name": "Appleseed",
"role": "Signer",
"recipient_type": "signer",
"has_completed": true,
"type": "recipient"
}
}
],
"pricing": {
"tables": [
{
"id": 82307036,
"name": "PricingTable1",
"is_included_in_total": true,
"summary": {
"discount": 10,
"tax": 0,
"total": 60,
"subtotal": 60
},
"items": [
{
"id": "4ElJ4FEsG4PHAVNPR5qoo9",
"qty": 1,
"name": "Toy Panda",
"cost": "25",
"price": "53",
"description": "Buy a Panda",
"custom_fields": {
"sampleField": "Sample Field"
},
"custom_columns": {
"sampleColumn": "Sample Column"
},
"discount": 10,
"subtotal": 60
}
],
"total": 60
}
]
},
"tags": [
"test tag",
"sales",
"support"
]
}
}
]
I would really appreciate a tip. Thank you
If you store your JSON object into variable called obj you can access that value ("Toy Panda") with:
obj.data.pricing.tables[0].items[0].name
because tables and items are arrays.
Here is a sample example :
<script>
var data = '{"name": "mkyong","age": 30,"address": {"streetAddress": "88 8nd Street","city": "New York"},"phoneNumber": [{"type": "home","number": "111 111-1111"},{"type": "fax","number": "222 222-2222"}]}';
var json = JSON.parse(data);
alert(json["name"]); //mkyong
alert(json.name); //mkyong
</script>
Refer this link :[https://www.mkyong.com/javascript/how-to-access-json-object-in-javascript/][1]
In your case it should be something like :
var data = // your json;
var json = JSON.parse(data);
console.log(json.pricing.tables.items[0].name;

Access and change 2d Json Array, Javascript

I'm trying to access and change the data I receive from a JSON api call.
The format of the call is like this:
{
"count": 391,
"value": [
{
"id": "id1",
"name": "name1",
"url": "url1",
"project": {
"id": "projId",
"name": "BT-GIT",
"url": "otherurl",
"state": "wellFormed"
},
"defaultBranch": "master",
"remoteUrl": "remote"
},
{
"id": "id2",
"name": "name2",
"url": "url2",
"project": {
"id": "projId",
"name": "BT-GIT",
"url": "otherurl",
"state": "wellFormed"
},
"defaultBranch": "master",
"remoteUrl": "remote"
},...
and I want to add an extra entry to each "value", such that I have:
{
"id": "id1",
"name": "name1",
"url": "url1",
"project": {
"id": "projId",
"name": "BT-GIT",
"url": "otherurl",
"state": "wellFormed"
},
"defaultBranch": "master",
"remoteUrl": "remote"
"date": "date" <---------
}
I've tried:
$.each(data, function (idx) {
data.value[idx].currentDate = new Date().toJSON().slice(0, 16);
})
and:
$.each(data, function (idx) {
data[1][idx].currentDate = new Date().toJSON().slice(0, 16);
})
any Ideas on how I could remedy this problem?
Much thanks.
You can do with your existing code but just need slightly tweaking,
var data = {
"count": 391,
"value": [{
"id": "id1",
"name": "name1",
"url": "url1",
"project": {
"id": "projId",
"name": "BT-GIT",
"url": "otherurl",
"state": "wellFormed"
},
"defaultBranch": "master",
"remoteUrl": "remote"
}, {
"id": "id2",
"name": "name2",
"url": "url2",
"project": {
"id": "projId",
"name": "BT-GIT",
"url": "otherurl",
"state": "wellFormed"
},
"defaultBranch": "master",
"remoteUrl": "remote"
}]
};
$.each(data.value, function (index,data) {
data.currentDate = new Date().toJSON().slice(0, 16);
});
console.log(data);
See Demo : https://jsfiddle.net/mj3vu6s6/4/
data.value = data.value.map(function(v) { v.date = Date.now() })

Categories

Resources