Converting a JSON Array to Repeating HL7 Segments¶
When a JSON source contains an array of related items, e.g. a list of appointment slots, and the target is an HL7 message that carries one segment per item (SIU with one AIS per appointment slot, ORM with one OBX per observation, etc.), iterate the array in a mapping script and add one segment per iteration. If the target segments need to be in a specific order, chronological, alphabetical, priority. Sort the array before iterating (see Sorting before iterating below).
Two building blocks:
source.getCount(path). Number of elements the array path resolves to. Append/[]and use it for the loop bound.source.getNode(path, i). The value of theith match (1-based). The path can address any field inside the current array element.
Add each segment with message.addChild('/', 'AIS') (or the target segment name), then set the fields with message.setNode.
var slotCount = source.getCount('/appointment/slots/slot/[]');
for (var i = 1; i <= slotCount; i++) {
// Append a new AIS segment to the outbound HL7 message.
message.addChild('/', 'AIS');
// Position the setNode calls at the newly-appended segment by using
// the loop index as the AIS repetition.
message.setNode('AIS-1.1', i, i); // set number
message.setNode('AIS-3.1', source.getNode('/appointment/slots/slot/procedureId', i), i);
message.setNode('AIS-3.2', source.getNode('/appointment/slots/slot/procedureName', i), i);
message.setNode('AIS-4.1', source.getNode('/appointment/slots/slot/startTime', i), i);
message.setNode('AIS-5.1', source.getNode('/appointment/slots/slot/durationMin', i), i);
}
The third argument to setNode is the segment repetition. Matching the loop index keeps the values landing in the segment just added rather than overwriting the first AIS on every iteration.
Note
Use the /[] array filter when counting elements, so the loop bound reads the same as the getNode paths that address each element. See Counting Elements.
Nested arrays¶
For array-in-array structures (e.g. each slot has a list of participating providers), nest the loops using the outer index to scope the inner path lookups:
var slotCount = source.getCount('/appointment/slots/slot/[]');
for (var i = 1; i <= slotCount; i++) {
message.addChild('/', 'AIS');
message.setNode('AIS-1.1', i, i);
var providerCount = source.getCount('/appointment/slots/slot/[' + i + ']/providers/provider/[]');
for (var j = 1; j <= providerCount; j++) {
message.addChild('/', 'AIP');
message.setNode('AIP-3.1', source.getNode('/appointment/slots/slot/[' + i + ']/providers/provider/npi', j), j);
message.setNode('AIP-3.2', source.getNode('/appointment/slots/slot/[' + i + ']/providers/provider/lastName', j), j);
}
}
The /[i] index on the inner path anchors to the current outer slot, so getCount and getNode see only that slot's providers. As with the outer array, append /[] to the provider path so getCount returns the provider count rather than 1.
Sorting before iterating¶
source.getCount / source.getNode walk the array in the order it appears in the payload. To emit HL7 segments in a different order, e.g. slots sorted chronologically by start time. Extract the array as JavaScript objects with JSON.parse, sort with a standard Array.sort comparator, then iterate the sorted result:
var slotsJson = source.getAllNodes('/appointment/slots/slot')[0];
var slots = JSON.parse(slotsJson);
slots.sort(function (a, b) {
return a.startTime < b.startTime ? -1 : (a.startTime > b.startTime ? 1 : 0);
});
for (var i = 0; i < slots.length; i++) {
message.addChild('/', 'AIS');
message.setNode('AIS-1.1', i + 1, i + 1);
message.setNode('AIS-3.1', slots[i].procedureId, i + 1);
message.setNode('AIS-3.2', slots[i].procedureName, i + 1);
message.setNode('AIS-4.1', slots[i].startTime, i + 1);
message.setNode('AIS-5.1', slots[i].durationMin, i + 1);
}
The comparator returns a negative number when a should come first, positive when b should come first, and zero when the order does not matter, the standard JavaScript sort contract. Use whatever field or combination of fields the target order requires.
If the sorted list needs to be written back into the JSON message rather than converted to HL7, use message.setJSONObject:
setJSONObject accepts any JavaScript object, including the array produced by Array.sort.