JavaScript nested array processing issue in n8n workflow

I’m working with an API that returns complex nested data structures in my n8n workflow. The JavaScript function node I’m using processes most of the data correctly, but I’m having trouble with deeply nested arrays. Here’s what I’m dealing with:

Sample input data:

{
  "status": "ok",
  "posts": [
    {
      "id": "xyz789",
      "headline": "sample title content",
      "description": "sample description text",
      "visibility": "open",
      "created": "2021-08-15T10:30:00.000+00:00",
      "url": "https://example.com/sample",
      "labels": [],
      "keywords": [
        "term1",
        "term2",
        "term3"
      ],
      "metrics": [
        {
          "category": "sample metric type",
          "total": 7,
          "items": [
            "value1",
            "value2",
            "value3"
          ],
          "origin": "external"
        }
      ]
    }
  ]
}

My current processing code:

const output = []
for (const record of records) {
  output.push.apply(output, record.json.posts)
}

return output.map(item => {
  const data = {};
  for (const field of Object.keys(item)) {
    if (field === 'keywords') {
      data[field] = item[field].toString().replace(/,/g, '\n');
      continue;
    }
    if (field === 'metrics') {
      data[field] = item[field].map(entry => entry.title).toString().replace(/,/g, '\n');
      continue;
    }
    data[field] = typeof item[field] === 'object' ? JSON.stringify(item[field]) : item[field];
  }
  return { json: data };
})

The problem is that the metrics field comes out empty in my final output. I think there’s an issue with how I’m accessing the nested array properties. Any ideas on how to fix this?

Hit the same issue last week. Besides the property name thing everyone mentioned, you’ll want to handle empty or missing nested arrays. Your code breaks if item[field] is undefined. Add a check like item[field] && item[field].length > 0 before mapping. Also think about what you’re pulling from the metrics array - you’ve got category, total, items, and origin. I ended up combining properties for better output, like entry.category + ' (' + entry.total + ')' to keep both the metric type and count.

Yeah, lucask’s right, but heads up - your .toString().replace(/,/g, '\n') won’t work like you think. Just use .join('\n') instead. Way cleaner and actually handles arrays correctly.

Found your problem. You’re trying to access entry.title but your metrics objects don’t have a title property. Your data structure shows each metric has category, total, items, and origin fields. Change this line:

data[field] = item[field].map(entry => entry.title).toString().replace(/,/g, '\n');

To this:

data[field] = item[field].map(entry => entry.category).toString().replace(/,/g, '\n');

Or grab more info from the metrics:

data[field] = item[field].map(entry => `${entry.category}: ${entry.total}`).toString().replace(/,/g, '\n');

That’ll fix your empty output. The wrong property name was making the map function return undefined values.