Home > Blockchain >  JavaScript - Array and Nested Objects
JavaScript - Array and Nested Objects

Time:08-04

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
}]
  • Related