0

I have an API call that returns the following JSON:

{
"name": "Ethereum 2.0",
"symbol": "ETH",
"slug": "ethereum-2-0",
"meta": {
 "start": "2022年08月03日T02:43:56Z",
 "startTimestamp": 1659494636000000000,
 "end": "2022年08月04日T02: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)
}
asked Aug 4, 2022 at 3:45
2
  • I imagine myObject.data.map(some_deeply_recursive_function) Commented Aug 4, 2022 at 3:49
  • Add some code for things you've tried - SO users generally appreciate when you show that you've put in an effort. It's usually easier to work from broken code than from scratch, and as the person asking the question you'll probably learn more too Commented Aug 4, 2022 at 3:51

2 Answers 2

1

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"

answered Aug 4, 2022 at 4:40
1
  • This worked perfectly in Retool (the platform in which I'm building my application). Thank you so much for answering, I can finally get some sleep! :) Commented Aug 4, 2022 at 4:51
1

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月03日T02:43:56Z",
 "startTimestamp": 1659494636000000000,
 "end": "2022年08月04日T02: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
}]
answered Aug 4, 2022 at 4:14
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.