I have an API call that returns the following JSON:
{
"name": "Ethereum 2.0",
"symbol": "ETH",
"slug": "ethereum-2-0",
"meta": {
"start": "2022-08-03T02:43:56Z",
"startTimestamp": 1659494636000000000,
"end": "2022-08-04T02:43:56Z",
"endTimestamp": 1659581036000000000
},
"data": [{
"timestamp": 1659579311,
"totalStaked": 10.795673641155977,
"engagedBalance": 13151223,
"inflation": 0.49479127486939656,
"rewardOptions": [{
"Name": "Run a Validator",
"Reward": 4.583236686436322,
"AdjustedReward": 4.068315740250017
},
{
"Name": "Validator-as-a-Service",
"Reward": 3.7811702663099656,
"AdjustedReward": 3.2701983354060715
},
{
"Name": "Exchange Staking",
"Reward": 3.899917762276725,
"AdjustedReward": 3.388361171967369
}]
},
{
"timestamp": 1659572709,
"totalStaked": 10.795673641155977,
"engagedBalance": 13151223,
"inflation": 0.49479127486939656,
"rewardOptions": [{
"Name": "Run a Validator",
"Reward": 4.583236686436322,
"AdjustedReward": 4.068315740250017
},
{
"Name": "Validator-as-a-Service",
"Reward": 3.7811702663099656,
"AdjustedReward": 3.2701983354060715
},
{
"Name": "Exchange Staking",
"Reward": 3.899917762276725,
"AdjustedReward": 3.388361171967369
}]
}
]
}
I am trying to flatten the "data" array in Javascript to create the following outcome:
[{
"timestamp": 1659579311,
"totalStaked": 10.795673641155977,
"engagedBalance": 13151223,
"inflation": 0.49479127486939656,
"rewardOptions[0].Name": "Run a Validator",
"rewardOptions[0].Reward": 4.583236686436322,
"rewardOptions[0].AdjustedReward": 4.068315740250017,
"rewardOptions[1].Name": "Validator-as-a-Service",
"rewardOptions[1].Reward": 3.7811702663099656,
"rewardOptions[1].AdjustedReward": 3.2701983354060715,
"rewardOptions[2].Name": "Exchange Staking",
"rewardOptions[2].Reward": 3.899917762276725,
"rewardOptions[2].AdjustedReward": 3.388361171967369
},{
"timestamp": 1659572709,
"totalStaked": 10.795673641155977,
"engagedBalance": 13151223,
"inflation": 0.49479127486939656,
"rewardOptions[0].Name": "Run a Validator",
"rewardOptions[0].Reward": 4.583236686436322,
"rewardOptions[0].AdjustedReward": 4.068315740250017,
"rewardOptions[1].Name": "Validator-as-a-Service",
"rewardOptions[1].Reward": 3.7811702663099656,
"rewardOptions[1].AdjustedReward": 3.2701983354060715,
"rewardOptions[2].Name": "Exchange Staking",
"rewardOptions[2].Reward": 3.899917762276725,
"rewardOptions[2].AdjustedReward": 3.388361171967369
}]
I have tried every .map, .flat, .forEach variety I can find, as well as about 30 different solutions I've found on Stack Overflow to flatten JSON responses (over the past 6 hours), but they'll either flatten the first 4 "data" keys and leave "rewardOptions" as an array of objects or create some other outcome other than what I'm wanting to achieve. The data is going to be displayed in a table, so I need the final result to be an array of objects so everything displays properly. Any help to get me unstuck would be greatly appreciated.
Update 1:
Here's the code for the closest-to-a-working version I had:
var data = {{ querysubmit.data.data }}
function flatten(array) {
var result = [];
array.forEach(function iter(o) {
var temp = {},
keys = Object.keys(o);
if (keys.length > 1) {
keys.forEach(function (k) {
if (k !== 'rewardOptions') {
temp[k] = o[k];
}
});
temp.rewardType1 = o.rewardOptions[0].Name;
temp.rewardRate1 = o.rewardOptions[0].Reward;
temp.adjustedRewardRate1 = o.rewardOptions[0].AdjustedReward;
temp.rewardType2 = o.rewardOptions[1].Name;
temp.rewardRate2 = o.rewardOptions[1].Reward;
temp.adjustedRewardRate2 = o.rewardOptions[1].AdjustedReward;
temp.rewardType3 = o.rewardOptions[2].Name;
temp.rewardRate3 = o.rewardOptions[2].Reward;
temp.adjustedRewardRate3 = o.rewardOptions[2].AdjustedReward;
result.push(temp);
}
Array.isArray(o.data) && o.temp.forEach(iter);
});
return result;
}
return flatten(data)
}
CodePudding user response:
If this is just a case, you can make your algorithm for the flatting array.
Here is one way to make that using loops.
const arr = {
"name": "Ethereum 2.0",
"symbol": "ETH",
"slug": "ethereum-2-0",
"meta": {
"start": "2022-08-03T02:43:56Z",
"startTimestamp": 1659494636000000000,
"end": "2022-08-04T02:43:56Z",
"endTimestamp": 1659581036000000000
},
"data": [{
"timestamp": 1659579311,
"totalStaked": 10.795673641155977,
"engagedBalance": 13151223,
"inflation": 0.49479127486939656,
"rewardOptions": [{
"Name": "Run a Validator",
"Reward": 4.583236686436322,
"AdjustedReward": 4.068315740250017
},
{
"Name": "Validator-as-a-Service",
"Reward": 3.7811702663099656,
"AdjustedReward": 3.2701983354060715
},
{
"Name": "Exchange Staking",
"Reward": 3.899917762276725,
"AdjustedReward": 3.388361171967369
}]
},
{
"timestamp": 1659572709,
"totalStaked": 10.795673641155977,
"engagedBalance": 13151223,
"inflation": 0.49479127486939656,
"rewardOptions": [{
"Name": "Run a Validator",
"Reward": 4.583236686436322,
"AdjustedReward": 4.068315740250017
},
{
"Name": "Validator-as-a-Service",
"Reward": 3.7811702663099656,
"AdjustedReward": 3.2701983354060715
},
{
"Name": "Exchange Staking",
"Reward": 3.899917762276725,
"AdjustedReward": 3.388361171967369
}]
}
]
}
let data = arr.data
let res = []
for(let i = 0; i < data.length; i ){
const objKeys = Object.keys(data[i]);
let obj = {}
for (let j = 0; j < objKeys.length; j ){
if(Array.isArray(data[i][objKeys[j]])){
flatArray(data[i][objKeys[j]], objKeys[j], obj)
} else {
const key = objKeys[j]
obj[key] = data[i][objKeys[j]]
}
}
res.push(obj)
}
function flatArray(arr, parentKey, res){
for (let j = 0; j < arr.length; j ){
const objKeys = Object.keys(arr[j]);
for(let i = 0; i < objKeys.length; i ){
const key = `${parentKey}[${j}].${objKeys[i]}`
res[key] = arr[j][objKeys[i]]
}
}
return res
}
console.log(res)
NOTE: "this solution will not work in case of different level nested arrays"
CodePudding user response:
So for every entry in myObject.data
, you should make a new object, and recursively add values to that new object.
let myObject = {
"name": "Ethereum 2.0",
"symbol": "ETH",
"slug": "ethereum-2-0",
"meta": {
"start": "2022-08-03T02:43:56Z",
"startTimestamp": 1659494636000000000,
"end": "2022-08-04T02:43:56Z",
"endTimestamp": 1659581036000000000
},
"data": [{
"timestamp": 1659579311,
"totalStaked": 10.795673641155977,
"engagedBalance": 13151223,
"inflation": 0.49479127486939656,
"rewardOptions": [{
"Name": "Run a Validator",
"Reward": 4.583236686436322,
"AdjustedReward": 4.068315740250017
},
{
"Name": "Validator-as-a-Service",
"Reward": 3.7811702663099656,
"AdjustedReward": 3.2701983354060715
},
{
"Name": "Exchange Staking",
"Reward": 3.899917762276725,
"AdjustedReward": 3.388361171967369
}]
},
{
"timestamp": 1659572709,
"totalStaked": 10.795673641155977,
"engagedBalance": 13151223,
"inflation": 0.49479127486939656,
"rewardOptions": [{
"Name": "Run a Validator",
"Reward": 4.583236686436322,
"AdjustedReward": 4.068315740250017
},
{
"Name": "Validator-as-a-Service",
"Reward": 3.7811702663099656,
"AdjustedReward": 3.2701983354060715
},
{
"Name": "Exchange Staking",
"Reward": 3.899917762276725,
"AdjustedReward": 3.388361171967369
}]
}
]
}
function recursiveAddProp(sourceObj, targetObj, keyPrefix) {
if (Array.isArray(sourceObj)) {
for (let i = 0; i < sourceObj.length; i ) {
recursiveAddProp(sourceObj[i], targetObj, keyPrefix `[${i}]`);
}
} else if (typeof sourceObj === 'object' && sourceObj !== null) {
for (let key in sourceObj) {
recursiveAddProp(sourceObj[key], targetObj, keyPrefix === '' ? key : keyPrefix '.' key)
}
} else {
targetObj[keyPrefix] = sourceObj;
}
}
const flattener = (data_entry) => {
let newObj = {}
recursiveAddProp(data_entry, newObj, '')
return newObj;
}
let flattenedObject = myObject.data.map(flattener);
console.log(JSON.stringify(flattenedObject))
Beautified output:
[{
"timestamp": 1659579311,
"totalStaked": 10.795673641155977,
"engagedBalance": 13151223,
"inflation": 0.49479127486939656,
"rewardOptions[0].Name": "Run a Validator",
"rewardOptions[0].Reward": 4.583236686436322,
"rewardOptions[0].AdjustedReward": 4.068315740250017,
"rewardOptions[1].Name": "Validator-as-a-Service",
"rewardOptions[1].Reward": 3.7811702663099656,
"rewardOptions[1].AdjustedReward": 3.2701983354060715,
"rewardOptions[2].Name": "Exchange Staking",
"rewardOptions[2].Reward": 3.899917762276725,
"rewardOptions[2].AdjustedReward": 3.388361171967369
}, {
"timestamp": 1659572709,
"totalStaked": 10.795673641155977,
"engagedBalance": 13151223,
"inflation": 0.49479127486939656,
"rewardOptions[0].Name": "Run a Validator",
"rewardOptions[0].Reward": 4.583236686436322,
"rewardOptions[0].AdjustedReward": 4.068315740250017,
"rewardOptions[1].Name": "Validator-as-a-Service",
"rewardOptions[1].Reward": 3.7811702663099656,
"rewardOptions[1].AdjustedReward": 3.2701983354060715,
"rewardOptions[2].Name": "Exchange Staking",
"rewardOptions[2].Reward": 3.899917762276725,
"rewardOptions[2].AdjustedReward": 3.388361171967369
}]