i have response data like this
{
"data": {
"title": "dashboard",
"description": "just test dashboard",
"photos": [
{
"file_name": "12345454.jpg",
"photo_name": "indonesia"
},
{
"file_name": "567686.jpg",
"photo_name": "jakarta"
}]
}
}
then i need change response of data with file_name of array without photos variable.
expected: file_name[0] will be sign from file_name index of array
like this
{
"data": {
"title": "dashboard",
"description": "just test dashboard",
"file_name[0]": "12345454.jpg",
"file_name[1]": "567686.jpg"
}
}
i have try with map of photos but didn't work
this.data = this.data.photos.map((item, idx) => {
let data = {
file_name: item.file_name
}
return data
})
this.data.photos.map((item, idx) => {
this.$set(this.data, 'file_name', item.file_name)
})
Try following
let data = {"title": "dashboard","description": "just test dashboard","photos":[{"file_name": "12345454.jpg","photo_name": "indonesia"},{"file_name": "567686.jpg","photo_name": "jakarta"}]};
data.photos.forEach((v,i) => data[`file_name[${i}]`] = v.file_name);
delete data.photos;
console.log(data);
I propose a soluce creating a new object.
#Nikhil Aggarwal soluce mutate the existing object
Both are good, pick your poison :)
const old = {
data: {
title: 'dashboard',
description: 'just test dashboard',
photos: [
{
file_name: '12345454.jpg',
photo_name: 'indonesia',
},
{
file_name: '567686.jpg',
photo_name: 'jakarta',
}],
},
};
const formatted = {
// We use reduce to create the data object
data: Object.keys(old.data).reduce((tmp, x) => {
// If we are not dealing with photos key, just add the old data to the new object
if (x !== 'photos') {
tmp[x] = old.data[x];
return tmp;
}
// for each photo, add a new key
old.data.photos.forEach((y, yi) => {
tmp[`file_name[${yi}]`] = y.file_name;
});
return tmp;
}, {}),
};
console.log(formatted);
If I understand correctly, you actually want file_name to be an array. If so, and you are happy to alter the object in place, try:
const obj = {
data: {
title: 'dashboard',
description: 'just test dashboard',
photos: [
{
file_name: '12345454.jpg',
photo_name: 'indonesia'
},
{
file_name: '567686.jpg',
photo_name: 'jakarta'
}]
},
}
obj.data.file_name = obj.data.photos.map(i => i.file_name)
delete obj.data.photos
console.log(obj)
have a look at this example. by using this you can restructure or create new you json.
<span id="text"></span><br/>
<span id="photosdata"></span>
here is the logic
var obj = JSON.parse('{ "data": { "title": "dashboard", "description": "just test dashboard", "photos": [ { "file_name": "12345454.jpg", "photo_name": "indonesia" }, { "file_name": "567686.jpg", "photo_name": "jakarta" }] } }');
document.getElementById("text").innerHTML = obj.data.title+"<br/>";
var photos = obj.data.photos;
photos.forEach(function(item){
document.getElementById("text").innerHTML += item.file_name +"<br/>";
});
https://jsfiddle.net/qufnwmd4/1/
Related
Is there a similar method to array.push that one can use to inject a new node into a json object?
I have an endpoint that requires a payload with dynamic element names based on what is being passed in, so i need to scrape the array and insert it into the payload for the correct format.
Example of the end-result payload i need:
{
"fields": {
"project": {
"key": projectKey
},
"summary": summary,
"description": description,
"issuetype": {
"name": issueType
},
"customfield_123456": "value1",
"customfield_7890": "value2"
}
}
This is the function in the controller that consumes the request body and attempts to inject the values in the customFields Array as elements in the json object but is not working:
const createIssueApi = async(req, res, next) => {
try {
let {
projectKey,
summary,
description,
issueType,
customFields
} = req.body;
console.log(req.body)
let jiraIssue = {
"fields": {
"project": {
"key": projectKey
},
"summary": summary,
"description": description,
"issuetype": {
"name": issueType
}
}
}
for (let ix = 0; ix < customFields.length; ix++) {
jiraIssue.fields[$ {
customFields[ix]
}] = customFields[ix];
}
console.log("Jira Issue payload: ", jiraIssue)
} catch (e) {
console.log(e)
}
}
This is the payload being sent in:
{
"projectKey": "JK",
"summary": "summary text",
"description": "THIS IS JUST A TEST",
"issueType": "Submit a request or incident",
"customFields": [{
"customfield_123456": "value1"
},
{
"customfield_7890": "value2"
}
]
}
there are methods
Array.prototype.push()
Array.prototype.pop()
Array.prototype.shift()
Array.prototype.unshift()
Array.prototype.concat()
for instance
const animals = ['pigs', 'goats', 'sheep'];
const count = animals.push('cows');
console.log(count);
// expected output: 4
console.log(animals);
// expected output: Array ["pigs", "goats", "sheep", "cows"]
animals.push('chickens', 'cats', 'dogs');
console.log(animals);
// expected output: Array ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"]
You appear to be attempting to use the same value for both the name and the value, and your Js seems to be invalid in that spot - [$ { is not valid js, but something like this should work
jiraIssue.fields[`customFields_${ix}`] = customFields[ix];
You can try using for...of and Object.entries inside for
const customFields = [{
'customfield_123456': 'value1'
},
{
'customfield_7890': 'value2'
}
];
const jiraIssue = {'fields': {}};
for (let ix = 0; ix < customFields.length; ix++) {
for (const [key, val] of Object.entries(customFields[ix])) {
jiraIssue.fields[key] = val;
}
}
console.log(jiraIssue);
The following is an example used with reduce
const restructure = (req) => {
const {customFields, ...rest} = req.body;
const fields = {
'project': {
"key": rest['projectKey']
},
'summary': rest['summary'],
'description': rest['description'],
'issuetype': {
"name": rest['issueType']
}
};
customFields.reduce((accumu, current) => {
for (const [key, val] of Object.entries(current)) {
accumu[key] = val;
}
return accumu;
}, fields);
return {fields};
}
const req = {
"body": {
"projectKey": "JK",
"summary": "summary text",
"description": "THIS IS JUST A TEST",
"issueType": "Submit a request or incident",
"customFields": [{
"customfield_123456": "value1"
},
{
"customfield_7890": "value2"
}
]
}
};
console.log(restructure(req));
I am trying to move everything in the Array Results outside and into the original object
this is the object
{
"Name": "John",
"Results": [
{
"Type": "DB",
"Immediate_Action": "No",
}
]
}
It should look like this
{
"Name": "John",
"Type": "DB",
"Immediate_Action": "No",
}
What I have so far is this
const mapOscarResults = ({ data }) => {
return data.map(entry => {
let mapped = {...entry};
entry.Results.forEach(key => {
let Type = mapped[key.Type]
if (mapped[key]) {
mapped[key].push(entry.Results[key]);
} else {
mapped[key] = [entry.Results[key]];
}
});
return mapped;
});
};
You can simply spread the Results array into an Object.assign() call.
const input = { "Name": "John", "Results": [{ "Type": "DB", "Immediate_Action": "No", }, { "Another": "value" }] };
const { Results, ...refactored } = input;
Object.assign(refactored, ...Results);
console.log(refactored)
This code works for your example:
const { Results: results, ...rest } = {
"Name": "John",
"Results": [
{
"Type": "DB",
"Immediate_Action": "No",
}
]
}
const res = {...rest, ...results.reduce((prev, curr) => ({
...prev,
...curr
}), {})}
console.log(res)
But I don't know what you expect when the Results array has more than one element.
In that condition, if this code does not fill your needs, ask me to change it.
however, it will join first Result with index 0, you can expand it
const data = {
"Name": "John",
"Results": [
{
"Type": "DB",
"Immediate_Action": "No",
}
]
}
const mapOscarResults = (data) => {
for (let i in Object.keys(data)){
if (Array.isArray(data[Object.keys(data)[i]])){
newKey = data[Object.keys(data)[i]][0]
data = {... data, ...newKey}
delete data[Object.keys(data)[i]]
}
}
return data
};
console.log(mapOscarResults(data))
I'm working on a react app that mimics a retail website. My main page displays an item, and below has card components of related products. When I click a button on one of the related products, I open a comparison modal that compares features of the current product and the clicked upon product. I figured that to accomplish this, I would create an array of the combined features of the clicked on product and the main page product. I've been struggling to get create an array of objects, where each unique feature has an object with data inside about the features and which product the feature belongs to.
As of right now, I've been able to get an array of all the features that the two products have, but this array has repeats if the products have overlapping features. This makes me unsure of how to render the comparison table because I was planning on mapping over the array and creating a table row for each feature. My current code to format these features is as follows:
formatFeatures: (currentProd, clickedProd) => {
let combinedFeatures = [];
if (clickedProd.features) {
clickedProd.features.forEach(feature => {
let obj = {}
let vals = Object.values(feature);
obj[vals[0]] = [vals[1], clickedProd.id]
combinedFeatures.push(obj)
})
}
currentProd.features.forEach(feature => {
let obj = {}
let vals = Object.values(feature);
obj[vals[0]] = [vals[1], currentProd.id]
combinedFeatures.push(obj)
})
let formattedFeatures = combinedFeatures.reduce((allFeatures, feature) => {
if (Object.keys(feature) in allFeatures) {
allFeatures = [allFeatures[Object.keys(feature)]].concat(feature);
} else {
allFeatures.push(feature);
}
return allFeatures;
}, [])
The result of this is:
[{
"Fabric": ["100% Cotton", 28214]
}, {
"Cut": ["Skinny", 28214]
}, {
"Fabric": ["Canvas", 28212]
}, {
"Buttons": ["Brass", 28212]
}]
This is pretty close to what I am looking for, where I have an array of objects that contain information about the feature and product id of the product, but the repeat in "Fabric" is something I'm struggling to sort out. Ideally, the result would look like this:
[{
"Fabric": ["100% Cotton", 28214],
["Canvas", 28212]
}, {
"Cut": ["Skinny", 28214]
}, {
"Buttons": ["Brass", 28212]
}]
If anyone can help guide me as to how to change my formatting function to accomplish this, I'd be very grateful. Alternatively, if anyone knows a better way to dynamically format a table with a single row for each unique feature given my current result, that would be great too.
The data coming into my helper function is as follows:
CurrentProd:
{
"id": 28212,
"name": "Camo Onesie",
"slogan": "Blend in to your crowd",
"description": "The So Fatigues will wake you up and fit you in. This high energy camo will have you blending in to even the wildest surroundings.",
"category": "Jackets",
"default_price": "140.00",
"created_at": "2021-07-10T17:00:03.509Z",
"updated_at": "2021-07-10T17:00:03.509Z",
"features": [{
"feature": "Fabric",
"value": "Canvas"
}, {
"feature": "Buttons",
"value": "Brass"
}]
}
ClickedProd:
{
"name": "Morning Joggers",
"category": "Pants",
"originalPrice": "40.00",
"salePrice": null,
"photo": "https://images.unsplash.com/photo-1552902865-b72c031ac5ea?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=300&q=80",
"id": 28214,
"features": [{
"feature": "Fabric",
"value": "100% Cotton"
}, {
"feature": "Cut",
"value": "Skinny"
}]
}
There seems to be a bigger question of how to structure your data. You say that ideally your results would look like:
[
{
"Fabric":
["100% Cotton",28214],
["Canvas",28212]
},
{
"Cut":
["Skinny",28214]
},
{
"Buttons":
["Brass",28212]
}
]
But what you're really trying to get out of this is a combined list of rows and associated values for each item feature, if it exists. All you really need then is an array of keys for each row you want to display, and objects that let you access the needed property by that key.
The array of keys could look like this:
["Fabric", "Cut", "Buttons"]
The objects you want to access the properties using those keys, for example your CurrentProd, could be this (notice that you can access a feature by calling CurrentProd.features["FeatureName"]):
{
"id":28212,
"name":"Camo Onesie",
// ... //
"features": {
"Fabric": "Canvas",
"Buttons": "Brass"
}
}
Having said that, to get those things you can get the array of keys, which we'll call allFeatureKeys, by reducing over a combined array of CurrentProd.features and ClickedProd.features:
const allFeatureKeys = [
...CurrentProd.features,
...ClickedProd.features
].reduce((acc, cur) => {
return acc.findIndex(cur.feature) > -1 ? [...acc, cur.feature] : acc
},
[]
);
And you can modify your CurrentProd to the above data shape by reducing over the array of its features, let's call this modifiedCurrentProd:
const modifiedCurrentProd = {
...CurrentProd,
features: CurrentProd.features.reduce((acc, cur) => {
return {...acc, [cur.feature]: cur.value}
}, {})
}
Repeat that for a modifiedClickedProd object, then you have both CurrentProd.features and ClickedProd.features values available for a lookup when you create your table values.
As an example only, since I don't know your react structure or what data you want to display, you can then render the values in the table rows mapping over the keys to make each row, and for each feature key, you access the value from the modifiedCurrentProd or modifiedClickedProd object's features property:
<div id="table">
{allFeatureKeys.map((featureKey) => {
return <div id="table-row">
<div>{featureKey}</div>
<div>
{
modifiedCurrentProd.features[featureKey] !== undefined
? modifiedCurrentProd.id
: "n/a"
}
</div>
<div>
{
modifiedClickedProd.features[featureKey] !== undefined
? modifiedClickedProd.id
: "n/a"
}
</div>
</div>
})}
</div>
Firstly the target data structure needs to be fixed/optimized. It looks like the OP does concentrate on something which is based on a generic Feature (like Fabric, Cut, Buttons) whereas such feature values seem to be associated more with the Product. Thus for one and the same feature the values are unique to the product feature. In order to not loose the product information, a target format's feature item needs to reflect its related product's id property.
A viable and still flexible enough target data structure then might look like this ...
{
"Fabric": [{
productId: 28214,
value: "100% Cotton",
}, {
productId: 28212,
value: "Canvas",
}],
"Cut": [{
productId: 28214,
value: "Skinny",
}],
"Buttons": [{
productId: 28212,
value: "Brass",
}],
}
Any approach should start with a data-normalizing mapping-process of a product's features list where each feature item will get its product related id assigned.
Thus a feature item like { feature: "Buttons", value: "Brass" } gets mapped temporarily into { productId: 28212, feature: "Buttons", value: "Brass" }.
The two normalized data-item lists now can be concatenated and finally processed/reduced into the final target structure ...
function mergeBoundProductId(item) {
return { ...this, ...item };
}
function aggregateProductFeatureValueLists(index, productFeature) {
const { feature, ...featureValue } = productFeature;
const featureList = index[feature] ??= [];
//const featureList = index[feature] || (index[feature] = []);
featureList.push(featureValue);
return index;
}
function createIndexOfProductFeatureValues(clickedProd, currentProd) {
const { features:clickedFeatures } = clickedProd;
const { features:currentFeatures } = currentProd;
return [
...clickedFeatures.map(mergeBoundProductId, { productId: clickedProd.id }),
...currentFeatures.map(mergeBoundProductId, { productId: currentProd.id }),
].reduce(aggregateProductFeatureValueLists, {});
}
const currentProduct = {
id: 28212,
name: "Camo Onesie",
// ... more properties ...
features: [{
feature: "Fabric",
value: "Canvas",
}, {
feature: "Buttons",
value: "Brass",
}],
};
const clickedProduct = {
name: "Morning Joggers",
// ... more properties ...
id: 28214,
features: [{
feature: "Fabric",
value: "100% Cotton",
}, {
feature: "Cut",
value: "Skinny",
}],
};
console.log(
'createIndexOfProductFeatureValues(clickedProduct, currentProduct) ...',
createIndexOfProductFeatureValues(clickedProduct, currentProduct)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
The advantage of breaking the code into dedicated processes comes with easier refactoring for e.g. changed target structures like something closer to what the OP was looking for.
The changes to the reducer function are minimal. It's just two changes, each barely noticeable in its line ...
function mergeBoundProductId(item) {
return { ...this, ...item };
}
function aggregateProductFeatureValueLists(index, productFeature) {
const { feature, productId, value } = productFeature;
const featureList = index[feature] ??= [];
featureList.push([value, productId]);
return index;
}
function createIndexOfProductFeatureValues(clickedProd, currentProd) {
const { features:clickedFeatures } = clickedProd;
const { features:currentFeatures } = currentProd;
return [
...clickedFeatures.map(mergeBoundProductId, { productId: clickedProd.id }),
...currentFeatures.map(mergeBoundProductId, { productId: currentProd.id }),
].reduce(aggregateProductFeatureValueLists, {});
}
console.log(
'createIndexOfProductFeatureValues(clickedProduct, currentProduct) ...',
createIndexOfProductFeatureValues(clickedProduct, currentProduct)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
const currentProduct = {
id: 28212,
name: "Camo Onesie",
// ... more properties ...
features: [{
feature: "Fabric",
value: "Canvas",
}, {
feature: "Buttons",
value: "Brass",
}],
};
const clickedProduct = {
name: "Morning Joggers",
// ... more properties ...
id: 28214,
features: [{
feature: "Fabric",
value: "100% Cotton",
}, {
feature: "Cut",
value: "Skinny",
}],
};
</script>
The last example's purpose too is to prove the advantage of an easy to refactor code base.
Here the main function gets renamed from createIndexOfProductFeatureValues to createListOfProductFeatureValues.
It's implementation also changes likewise but only in the way how the reducer function gets invoked with its initial value.
The reducer function also does not change dramatically, only in the way of how the accumulating/aggregating collector object gets handled.
And the result is a clean array based object structure ...
function mergeBoundProductId(item) {
return { ...this, ...item };
}
function aggregateProductFeatureValueLists(collector, productFeature) {
const { feature, productId, value } = productFeature;
const { index, list } = collector;
const featureItem = index[feature] ??= { feature, values: [] };
if (featureItem.values.length === 0) {
list.push(featureItem);
}
featureItem.values.push([value, productId]);
return collector;
}
function createListOfProductFeatureValues(clickedProd, currentProd) {
const { features:clickedFeatures } = clickedProd;
const { features:currentFeatures } = currentProd;
return [
...clickedFeatures.map(mergeBoundProductId, { productId: clickedProd.id }),
...currentFeatures.map(mergeBoundProductId, { productId: currentProd.id }),
].reduce(aggregateProductFeatureValueLists, { index: {}, list: [] }).list;
}
console.log(
'createListOfProductFeatureValues(clickedProduct, currentProduct) ...',
createListOfProductFeatureValues(clickedProduct, currentProduct)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
const currentProduct = {
id: 28212,
name: "Camo Onesie",
// ... more properties ...
features: [{
feature: "Fabric",
value: "Canvas",
}, {
feature: "Buttons",
value: "Brass",
}],
};
const clickedProduct = {
name: "Morning Joggers",
// ... more properties ...
id: 28214,
features: [{
feature: "Fabric",
value: "100% Cotton",
}, {
feature: "Cut",
value: "Skinny",
}],
};
</script>
You are already looping through both once. You can get it without reducing.
const formatFeatures = (currentProd, clickedProd) => {
const formattedFeatures = {};
if (clickedProd.features) {
clickedProd.features.forEach(feature => {
const vals = Object.values(feature);
if (!formattedFeatures.hasOwnProperty(vals[0])) {
formattedFeatures[vals[0]] = [];
}
formattedFeatures[vals[0]].push([vals[1], clickedProd.id]);
});
}
currentProd.features.forEach(feature => {
const vals = Object.values(feature);
if (!formattedFeatures.hasOwnProperty(vals[0])) {
formattedFeatures[vals[0]] = [];
}
formattedFeatures[vals[0]].push([vals[1], currentProd.id]);
})
return formattedFeatures;
}
const currentProd = {
"id": 28212,
"name": "Camo Onesie",
"slogan": "Blend in to your crowd",
"description": "The So Fatigues will wake you up and fit you in. This high energy camo will have you blending in to even the wildest surroundings.",
"category": "Jackets",
"default_price": "140.00",
"created_at": "2021-07-10T17:00:03.509Z",
"updated_at": "2021-07-10T17:00:03.509Z",
"features": [{
"feature": "Fabric",
"value": "Canvas"
}, {
"feature": "Buttons",
"value": "Brass"
}]
};
const clickedProd = {
"name": "Morning Joggers",
"category": "Pants",
"originalPrice": "40.00",
"salePrice": null,
"photo": "https://images.unsplash.com/photo-1552902865-b72c031ac5ea?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=300&q=80",
"id": 28214,
"features": [{
"feature": "Fabric",
"value": "100% Cotton"
}, {
"feature": "Cut",
"value": "Skinny"
}]
};
console.log(formatFeatures(currentProd, clickedProd));
.as-console-wrapper { min-height: 100%!important; top: 0; }
I have an object that I am parsing through to pass along.
It looks like this:
var inputDescriptions = {
customText: {
message: "this is a message",
note: "this is a note"
},
tool: "wrench",
garage: "two-door",
"garage-color": "white",
message: "message",
"message-color": "white",
note: "note"
};
At the end of the parsing, I want it to be an array of item and descriptions like so:
this is called "inputDescriptions"
[{
item: "tool",
description: "wrench"
}, {
item: "garage",
description: "two-door"
}, {
item: "garage-color",
description: "white"
}, {
item: "noteText",
description: "this is a note"
}, {
item: "messageText",
description: "this is a message"
}, {
item: "message",
description: "message"
}, {
item: "note",
description: "note"
}]
I'm getting really thrown off by the one item that is an object with two properties.
Here is the function as I have it:
const parseSelections = (inputDescriptions) => {
return Object.keys(inputDescriptions).map((choiceId) => {
const optionId = inputDescriptions[choiceId];
const userSelectionInput = {
choiceId,
optionId,
};
return userSelectionInput;
});
};
const selections = parseSelections(inputDescriptions);
It gets close but not quite there:
[
{item: "tool", description: "wrench"}
{item: "garage", description: "two-door"}
{item: "garage-color", description: "white"}
{item: "customText", description: {message: "this is a message", note: "this is a note"}
{item: "message", description: "message"}
{item: "note", description: "note"}
]
I tried to use Object.assign to pull out the customText object and reassign, but I still couldn't get it to work. Maybe I need to make a new function to parse through again? I feel like I'm so close but the object is throwing me off. Does anyone have a better idea of a clean way to do this?
You need to remove the customText property from the object and process it separately.
let inputDescriptions = {
customText: {
message: "this is a message",
note: "this is a note"
},
tool: "wrench",
garage: "two-door",
"garage-color": "white",
message: "message",
"message-color": "white",
note: "note"
};
const parseSelections = (inputDescriptions) => {
inputDescriptions = Object.assign({}, inputDescriptions); // clone object
let customText = inputDescriptions.customText;
delete inputDescriptions.customText;
return Object.keys(inputDescriptions).map((choiceId) => {
const optionId = inputDescriptions[choiceId];
const userSelectionInput = {
choiceId,
optionId,
};
return userSelectionInput;
}).concat(
Object.entries(customText).map(([key, val]) => ({
choiceId: `${key}Text`,
optionId: val
}))
);
};
const selections = parseSelections(inputDescriptions);
console.log(selections);
Just call your function recursively if the type of the input is an object :
if (typeof inputDescriptions[choiceId] === "object") {
return parseSelections(inputDescriptions[choiceId]);
}
the function will return a nested array the you can flat
const inputDescriptions = {
customText: {
message: "this is a message",
note: "this is a note"
},
tool: "wrench",
garage: "two-door",
"garage-color": "white",
message: "message",
"message-color": "white",
note: "note"
};
const parseSelections = (inputDescriptions, suff) => {
return Object.keys(inputDescriptions).map(choiceId => {
if (typeof inputDescriptions[choiceId] === "object") {
return parseSelections(inputDescriptions[choiceId], "Text");
} else {
const optionId = inputDescriptions[choiceId];
const userSelectionInput = {
[choiceId + suff]: choiceId,
optionId
};
return userSelectionInput;
}
});
};
const selections = parseSelections(inputDescriptions, '').flat();
console.log(selections);
I highly recommend restructuring you data, to save you development time and headache later down the line. adding to this would be a nightmare. You could you an object loop and spread the keys, with the values, but I would recommend making a new Arr of objects like this. It will be much easier to work with and anyone else reading the data will have a much better understanding of the data. With this Structure, you can loop through the items and if you need to loop through the object on that item. Hope it saves some headache.
let items = [
{
item: "tool",
description:"Wrench"
},
{
item: "garage",
description:"two-door",
garageColor:"some color"
},
{
item: "some item",
description:"des"
},
{
item: "tool two",
description:"Wrench 2"
},
{
item: "customText",
message:"this is a message",
note:"this is a note",
}
]
How can I get the names of different activity in an array by using map function in this type of response. So that in a new array, assume that activity[] i will get names of all the activities mention below.
if the array is
const response = [
{
"Groups" : {
"Roles" : {
"submission": {
"subject" : {
"name": "history",
}
}
}
}
}
];
I managed to do this using an IIFE but there may be cleaner ways
assuming there in one object in the array and no other path to other permission
const response = [
{
"Roles" : {
"Permission" : {
"PERMISSION1": {
"Activity" : {
"name": "Manage Clients",
}
},
"PERMISSION2": {
"Activity" : {
"name": "Manage Users",
}
}
}
}
}
];
let activities = (() => {
let res = []
for (let perm in response[0].Roles.Permission) {
for (let act in response[0].Roles.Permission[perm]) {
res.push(response[0].Roles.Permission[perm][act].name)
}
}
return res})()
console.log(activities)
At first, you should convert Permission object to array, cause object doesn't have method map.
Then you could use map function where you can collect all your permissions' names for every item in response
const response = [{
"Roles": {
"Permission": {
"PERMISSION1": {
"Activity": {
"name": "Manage Clients",
}
},
"PERMISSION2": {
"Activity": {
"name": "Manage Users",
}
}
}
}
}];
response.forEach((item) => {
item.Activities = Object.values(item.Roles.Permission).map((permission) => permission.Activity.name)
});
alert(JSON.stringify(response));
The only array you have is response. If each item in response has a Roles that has a Permission that has several keys with objects that have Activity with name then you can do the following:
var response = [
{
Roles: {
Permission: {
PERMISSION1: {
Activity: {
name: 'Manage Clients',
},
},
PERMISSION2: {
Activity: {
name: 'Manage Users',
},
},
},
},
},
];
console.log(
response.map(
(item) =>
Object.values(item.Roles.Permission)
.map(
(permission) => permission.Activity.name
)
)
);
I recommend using a flatMap, so use .reduce.
const response = [{
"Roles": {
"Permission": {
"PERMISSION1": {
"Activity": {
"name": "Manage Clients",
}
},
"PERMISSION2": {
"Activity": {
"name": "Manage Users",
}
}
}
}
}];
const activityNames = response.reduce(function (acc, res) {
const permissions = res.Roles.Permission;
const permissionKeys = Object.keys(permissions);
const names = permissionKeys.map(function(permissionKey) {
return permissions[permissionKey].Activity.name;
});
acc.push(...names);
return acc;
}, [])
console.log(activityNames); // ["Manage Clients", "Manage Users"]