Home > Mobile >  How to map JSON key value pairs when object parent name is different each time?
How to map JSON key value pairs when object parent name is different each time?

Time:04-09

I'm trying to map key value pairs (see investments in the below JSON) but the parent names are all different. It's proving difficult to search for the answer.

How do I go about targeting these data?

Many thanks in advance!

"quarterly": {
    "2021-12-31": {
            "date": "2021-12-31",
            "filing_date": "2022-01-28",
            "currency_symbol": "USD",
            "investments": "-12929000000.00"
    },
    "2021-09-30": {
            "date": "2021-09-30",
            "filing_date": "2021-10-29",
            "currency_symbol": "USD",
            "investments": "4608000000.00"
    },
    "2021-06-30": {
            "date": "2021-06-30",
            "filing_date": "2021-07-28",
            "currency_symbol": "USD",
            "investments": "5747000000.00"
    },
    "2021-03-31": {
            "date": "2021-03-31",
            "filing_date": "2021-04-29",
            "currency_symbol": "USD",
            "investments": "-7895000000.00"
    }, ...

Aiming to get something like this:

--------------------------------
|            |"Investment"     |
--------------------------------
|"2021-12-31"|"-12929000000.00"|
--------------------------------
|"2021-09-31"|"-4608000000.00" |
--------------------------------
|"2021-06-30"|"5747000000.00"  |
--------------------------------

CodePudding user response:

It's not very clear from your question what you need to do with the data.

You should explain what is the purpose of retrieving the investments data because you can use different approach.

If you need to manipulate the keys and the values on the fly (for example put them in a webpage in some format, you can use a combination of Object.entries and Array.forEach

Object.entries(items.quarterly).forEach(([itemKey, item], index) => {
    console.log(`Key at index ${index} is ${itemKey} and its value is ${item.investments}`)
})

If you need only the values, replace Object.entries with Object.values (for keys use Object.keys)

Object.values(items.quarterly).forEach((item, index) => { 
   console.log(`Value at index ${index} is ${item.investments}`)
})

Instead, if you need to save the data in an array use Object.entries (or Object.values or Object.keys, like above) and Array.map

const investments = Object.values(items.quarterly).map((item) => item.investments)

If you need to sum all the investments values to get the total you can use Object.values and Array.reduce

const investmentsTotal = Object.values(items.quarterly).reduce((tot, {investments}) => tot   parseFloat(investments), 0)

Here is a working example of the different approach

const el = document.querySelector("div")
const append = (text) => el.innerHTML  = `${text}<br/>`
const items = {
    "quarterly": {
        "2021-12-31": {
            "date": "2021-12-31",
            "filing_date": "2022-01-28",
            "currency_symbol": "USD",
            "investments": "-12929000000.00"
        },
        "2021-09-30": {
            "date": "2021-09-30",
            "filing_date": "2021-10-29",
            "currency_symbol": "USD",
            "investments": "4608000000.00"
        },
        "2021-06-30": {
            "date": "2021-06-30",
            "filing_date": "2021-07-28",
            "currency_symbol": "USD",
            "investments": "5747000000.00"
        },
        "2021-03-31": {
            "date": "2021-03-31",
            "filing_date": "2021-04-29",
            "currency_symbol": "USD",
            "investments": "-7895000000.00"
        }
    }
};



append(`<b>Example 1</b>: Keys and values:`)

// 1) For keys and values use this forEach statement
Object.entries(items.quarterly).forEach(([itemKey, {investments}], index) => {
  append(`Key at index ${index} is ${itemKey} and its value is ${investments}`)
})
append("")


append(`<b>Example 2</b>: only investments values:`)

// 2) For only values use this forEach statement
Object.values(items.quarterly).forEach(({investments}, index) => {
  append(`Value at index ${index} is ${investments}`)
})
append("")

append(`<b>Example 3</b>: get the values for later usage`)
// 3) To get an array of the values use this map statement
const investmentsList = Object.values(items.quarterly).map(({investments}) => investments)
append(`investmentsList =>  ${JSON.stringify(investmentsList, null, 2)}`)
append("")

append(`<b>Example 4</b>: sum the investments values`)
// To sum all the values use this reduce statement
const investmentsTotal = Object.values(items.quarterly).reduce((tot, {investments}) => tot   parseFloat(investments), 0)
append(`Investments total = ${investmentsTotal}`)
append("")

append(`Done`)
<div></div>

In all the examples I used destructuration. All the functions receive the whole map where investments key is:

const item = {
    "date": "2021-12-31",
    "filing_date": "2022-01-28",
    "currency_symbol": "USD",
    "investments": "-12929000000.00"
}
// Instead of writing:
const investments = item.investments
// I used the destructuration:
const {investments} = item

Using it directly in the argument I didn't need to name the item variable, it was implicit.

CodePudding user response:

bago's answer has a lot more detail, but I believe there is value in another brief explanation after your edit.

If we know how many levels deep the object is, and all the items will have the same keys, we can just loop through things. You could package this destructuring many different ways, and even get even spacing in a table printed to the console if that's your goal. However, I believe your main goal is to get the information to work with rather than explicitly putting it into a table.

I will break my code down line by line to further clarify.

  1. I initialize a variable named outputData and give it an initial value of an array which is going to contain arrays. At index 0 on initialization, there in an array which is acting kind of like a legend, or header row in excel.
  2. I use object destructuring assignment to quickly pull out the quarterly value from someObj
  3. I convert the quarterly object into entries. Basically an object {"foo": "bar"} becomes and array [ ["foo", "bar"] ] of key value pairs.
  4. I loop through these key value pairs again, using destructuring for the loop variable
  5. for each loop iteration I am pushing another array to the objectData array, that array following the same header pattern I started with
  6. After the loop I am just formatting the data into a human readable way (csv style)

If you have any questions please ask.

const someObj = {
  "quarterly": {
    "2021-12-31": {
      "date": "2021-12-31",
      "filing_date": "2022-01-28",
      "currency_symbol": "USD",
      "investments": "-12929000000.00"
    },
    "2021-09-30": {
      "date": "2021-09-30",
      "filing_date": "2021-10-29",
      "currency_symbol": "USD",
      "investments": "4608000000.00"
    },
    "2021-06-30": {
      "date": "2021-06-30",
      "filing_date": "2021-07-28",
      "currency_symbol": "USD",
      "investments": "5747000000.00"
    }
  }
};


const outputData = [
  ["Key", "Investment", "filing_date", "currency_symbol"],
];
const {quarterly} = someObj;
const entries = Object.entries(quarterly);
for (const [key, val] of entries) {
  outputData.push([
    key,
    val["investments"],
    val["filing_date"],
    val["currency_symbol"]
  ]);
}
const outputString = outputData.map(arr => arr.join(", ")).join("\n");
console.log(outputString);

  • Related