简体   繁体   English

JavaScript - 数组和嵌套对象

[英]JavaScript - Array and Nested Objects

I have an API call that returns the following JSON:我有一个 API 调用,它返回以下 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:我正在尝试展平 Javascript 中的“数据”数组以创建以下结果:

[{
"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.我已经尝试过每一个。map、.flat、.forEach 品种,以及我在 Stack Overflow 上找到的大约 30 种不同的解决方案,以使 JSON 响应变平(过去 6 小时内),但它们要么变平前 4 个“数据”键并将“rewardOptions”保留为对象数组,或者创建一些其他结果,而不是我想要实现的结果。 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:更新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)

}

So for every entry in myObject.data , you should make a new object, and recursively add values to that new object.因此,对于myObject.data中的每个条目,您应该创建一个新的 object,并递归地将值添加到新的 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:美化 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
}]

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 "注意:“此解决方案不适用于不同级别的嵌套 arrays

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM