I am trying to create a new Array of Object
from the data which is another array of objects coming from API.
The new Array which we will get in the end should get value from dataFromApi
and updated key names to will be selected from another array that holds the previous key
and new key name | label
for those properties. This data will be exported in CSV file. So we are using reusable components for this export, I want to make this conversion of data dynamic. As the current key name looks like currentApplyStart
and in the CSV file they are not good headers.
So,
We are getting a new key names array from this function. What this function is trying to solve is, get the pair of oldKeyName and its newKeyName || new key and label
const newKeyName = () => { if (data?.length) { const allColumn = Object.keys(data?.[0]); const columnKeys = dataColumns .filter((header) => allColumn.indexOf(header.key) >= 0) .map((column) => { return { key: column.key, label: column.label }; }); return columnKeys; }; }
which return something like this. This is demo data.
let dataColumns = [ {key : 'color', label : 'newColor'} , {key : 'annoying', label : 'newAnnoying'}, key : 'height', label : 'newHeight'} // we only return these top three as the api data object consist only has these two keys in itself. {key : 'meta', label : 'newMeta'} {key : 'costApplyStart', label : 'CPA'} ]
let newKeyNames = [ {key : 'color', label : 'newColor'} , {key : 'annoying', label : 'newAnnoying'}, {key : 'height', label : 'newHeight'} ] // as only these three key name exist in dataFromApi.
So let’s say we have an array of the object which comes from API
let DataFromApi = [ { color: 'red', annoying: true, height: 'unknown', }, { color: 'blue', annoying: false, height: 'unknown', }, { color: 'red', annoying: false, height: 'unknown', }, ];
The data which i want it in the end should be like this
let finalData = [ {newColor: 'red',newAnnoying: true, newHeight: 'unknown',}, {newColor: 'blue',newAnnoying: false, newHeight: 'unknown',} { color: 'red', annoying: 'false, newHeight: 'unknown', }, ]
Observe is data, that I changed the old key name into a new key which I want to be header in csvFile. I can not mutate the original data , for that reason i have to create a new data array . The solution i tried was this but I was not getting the desired result.
newKeyNames?.map((field) => { return dataFromAPi.map((item) => { if (item.hasOwnProperty(field.key)) { item[field.label] = item[field.key]; } }); });
Advertisement
Answer
Based on the later explanation, I’ve updated the answer.
Here’s the JSFiddle link: https://jsfiddle.net/_ghost/py8et9vf/57/
let DataFromApi = [ { color: 'red', annoying: true, height: 'unknown', meta: { one: '1', two: '2'} }, { color: 'blue', annoying: false, height: 'unknown', meta: { one: '1', two: '2'} }, { color: 'red', annoying: true, height: 'unknown', meta: { one: '1', two: '2'} }, ]; let dataColumns = [ {key : 'color', label : 'newColor'} , {key : 'annoying', label : 'newAnnoying'}, {key : 'somekey', label : 'newSomeKey'}, {key : 'anotherKey', label : 'newAnotherKey'} ] function getAllDataCols(){ let obj = {}; // Make a new object from all the dataColums for ease of use dataColumns.forEach(item => { obj[item.key] = item.label }) return obj } function processDataFromApi(newDataCols){ let result = [] DataFromApi.forEach(obj => { let newObj = {} Object.keys(obj).forEach(name => { if(newDataCols[name] !== undefined){ //if we have an alternative for the name newObj[newDataCols[name]] = obj[name] }else{ // we don't have an alternative. use the already existing name newObj[name] = obj[name] } }) result.push(newObj) }) return result } let newDataCols = getAllDataCols() let response = processDataFromApi(newDataCols) console.log(response)