Skip to content

Converting a JSON Array to a CSV Message

When a JSON source contains an array of objects that all share the same shape, e.g. a list of orders, patients, or scheduled slots, a common target is a flat CSV with one row per object and column headers taken from the object's keys. Build a fresh CSV message with qie.createCSVMessage, then fill in the rows with setNode.

// Parse the JSON array once.
var arrayJson = source.getAllNodes('/orders/order')[0];
var rows = JSON.parse(arrayJson);
if (!Array.isArray(rows)) {
    rows = [rows];  // single-element source that got flattened out of an array
}

// Take the column list from the first row's keys, and use those as the CSV
// header row that createCSVMessage seeds the message with.
var columns = Object.keys(rows[0]);
var csv = qie.createCSVMessage(columns.join(','));

// Set each cell by column name and 1-based row instance. setNode auto-adds
// rows as new instances are referenced.
for (var i = 0; i < rows.length; i++) {
    for (var k = 0; k < columns.length; k++) {
        var col = columns[k];
        var raw = rows[i][col];
        csv.setNode(col, raw == null ? '' : String(raw), i + 1);
    }
}

// Hand the finished CSV back as the outbound message.
message.setNode('/', csv.toString());

Object.keys(rows[0]) handles the column list generically; if the objects have a fixed known shape, hard-coding the array keeps the header ordering explicit:

var columns = ['orderId', 'patientId', 'orderedTest', 'orderedAt'];

Field ordering and missing keys

Object.keys returns properties in insertion order, which for JSON parsed by JSON.parse matches the order they appeared in the source. If different rows in the source array have different keys (some optional field is missing from some rows), rows[i][col] returns undefined for the missing cells; the raw == null ? '' guard turns that into an empty cell rather than the string undefined.

Nested objects

CSV cells are strings. For a JSON row whose value is itself an object or array ({"name": {"first": "A", "last": "B"}}), flatten before assignment, either by JSON-stringifying the nested value or by pulling out the specific fields you want as separate columns:

var columns = ['orderId', 'patientLast', 'patientFirst', 'orderedTest'];
var csv = qie.createCSVMessage(columns.join(','));

for (var i = 0; i < rows.length; i++) {
    csv.setNode('orderId',      rows[i].orderId,           i + 1);
    csv.setNode('patientLast',  rows[i].patient.last,      i + 1);
    csv.setNode('patientFirst', rows[i].patient.first,     i + 1);
    csv.setNode('orderedTest',  rows[i].orderedTest,       i + 1);
}