'Loop through array of differently structured JSON objects/arrays
I feel like this is mostly an issue with how I'm looping through the JSON, so am posting that first. This is a series of JSON responses from Promise.allSettled() posted below.
The problem I am having is with the second "status" object between content and anoObject1 as I'm looping through the JSON responses. I've shown some console.logs() below that are successful
Here is the series of JSON responses:
[
{
"status": "fulfilled",
"value": {
"content": {
"object1": {
"kv": "Y",
"kv1": "1000",
"kv2": {
"okv": "A",
"okv1": "1"
},
"kw": "A"
}
},
"retrievalDate": "2022-05-04T23:01:57.710+0000"
}
},
{
"status": "fulfilled",
"value": {
"content": [
{
"anoObject1": {
"ano": "A",
"ano1": {
"ona": "B",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
},
{
"anoObject2": {
"ano": "B",
"ano1": {
"ona": "Y",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
}
],
"retrievalDate": "2022-05-04T23:01:57.707+0000"
}
}
]
Here are the async fetch calls:
export async function allCallouts(key, value){
const BASE_URL = 'https://baseurl.com/service/'
const API_KEY = 'apikey'
const endpoint1 = 'https://url1.com/a/';
const endpoint2 = 'https://url1.com/b/';
try{
const results = await Promise.allSettled(
[
fetch(endpoint1).then((response) => response.json()),
fetch(endpoint2).then((response) => response.json()),
]
)
return results
} catch (error){
console.log(error)
}
}
Here is the function I am calling the first function from
async handleFetchCallouts() {
returnedResults;
await allCallouts(key, value)
.then(results => {
this.returnedResults = results
}).catch(err => {
console.log('this is err: ' + err);
})
let arrayLength = this.returnedResults.length
for (var i = 0; i < arrayLength; i++) {
//I am able to console.log(this.returnedResults[i].value.content)
//it returns the response and number I am expecting
//but the structure of the JSON response (above) is tripping me up
if (this.returnedResults[i].value.content['object1'] != null) {
//I can console.log() this successfully
console.log(this.returnedResults[i].value.content['object1'].kv)
}
if (this.returnedResults[i].value.content['anoObject1'] != null) {
//having trouble getting to this object and looping through each
}
}
}
Thank you for any help! If you see other design flaws with my code or an easier way to do things, please suggest.
Solution 1:[1]
Create a recursive function and dont use any hardcoded key. Iterate through the content and check if value is an array using Array.isArray. If so then handle it in a different function and so for if value is of type object
const arrayLength = [{
"status": "fulfilled",
"value": {
"content": {
"object1": {
"kv": "Y",
"kv1": "1000",
"kv2": {
"okv": "A",
"okv1": "1"
},
"kw": "A"
}
},
"retrievalDate": "2022-05-04T23:01:57.710+0000"
}
},
{
"status": "fulfilled",
"value": {
"content": [{
"anoObject1": {
"ano": "A",
"ano1": {
"ona": "B",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
},
{
"anoObject1": {
"ano": "B",
"ano1": {
"ona": "Y",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
}
],
"retrievalDate": "2022-05-04T23:01:57.707+0000"
}
}
]
for (let i = 0; i < arrayLength.length; i++) {
const content = arrayLength[i].value.content;
// checking if value is of type array or object
if (Array.isArray(content)) {
handleContentArray(content)
} else if (content && typeof(content) === 'object') {
handleContentObject(content)
}
}
function handleContentArray(contentArray) {
// iterate the array
contentArray.forEach(item => {
// if the content of the array is an object then call the function which handles the object
if (item && typeof item === 'object') {
handleContentObject(item)
}
})
}
function handleContentObject(contentObject) {
// iterate through the key
for (let keys in contentObject) {
// if the value of the key is an object then recursively call the same function
if (contentObject && typeof(contentObject[keys]) === 'object') {
return handleContentObject(contentObject[keys])
} else {
// log the key value pair
console.log(`KEY:- ${keys}, VALUE: - ${contentObject[keys]}`)
}
}
}
Solution 2:[2]
You can use Array.isArray() to ascertain if an object is an Array and customize how you handle the object accordingly.
// Same structure as in the question, but removed extraneous
// fields and compacted for the sake of brevity.
const input = `[
{"value":{"content":{"object1":{"kv":"Y"}}}},
{"value":{"content":[
{"anoObject1":{"ano":"A"}},
{"anoObject1":{"ano":"B"}}
]}}]`;
const result = JSON.parse(input);
for (const r of result) {
const content = r.value.content;
if (Array.isArray(content)) {
for (const c of content) {
console.log(`anoObject1.ano = ${c.anoObject1.ano}`);
}
} else {
console.log(`object1.kv = ${content.object1.kv}`);
}
}
Solution 3:[3]
For your second if statement in the for loop, you would have to iterate through all items under value.content. Replace the second if statement with this for a plug and play:
if (Array.isArray(this.returnedResults[i].value.content)) for (let i of this.returnedResults[i].value.content) {
}
Inside the new loop, i will be equivalent to
{
"anoObject1": {
"ano": "A",
"ano1": {
"ona": "B",
"ona1": 11
},
"measureValue": "1.92",
"measureValue2": "N"
}
}
The reason for this is that the second if statement was attempting to find a property/key of an array instead of each object in the array of objects.
I would also recommend reading up on the following to make your coding easier/better:
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | brk |
| Solution 2 | chuckx |
| Solution 3 | Thomasc-3 |
