---> [{"#listGetAt(#columnsOut#,i)#":"#qry[listGetAt(#columnsIn#,i)]#",},] ---> #query2json(ATTRIBUTES.qRead,ATTRIBUTES.convertSnakeToCamel)# public string function customJson(required any data) { return serializeJson(formatDatesToIso(arguments.data)); } private any function formatDatesToIso(required any input) { // 1. Handle Dates (Strict verification using isValid and checking underlying type) // Lucee dates are typically objects (java.util.Date / java.time). // This prevents strings like "12345" or "Yes" from being treated as dates. if (isDate(arguments.input) && (isObject(arguments.input) || !isValid("integer", arguments.input))) { return dateTimeFormat(arguments.input, "iso8601"); } // 2. Handle Structs (Preserve case-sensitivity using [:] syntax) if (isStruct(arguments.input)) { var newStruct = [Ordered: true]; // Lucee/CF literal for preserving key case for (var key in arguments.input) { newStruct[key] = formatDatesToIso(arguments.input[key]); } return newStruct; } // 3. Handle Arrays if (isArray(arguments.input)) { var newArray = []; for (var item in arguments.input) { arrayAppend(newArray, formatDatesToIso(item)); } return newArray; } // 4. Handle Queries if (isQuery(arguments.input)) { var queryArray = []; var columns = arguments.input.getColumnNames(); // Returns correct case array loop query="arguments.input" { var rowStruct = [Ordered: true]; loop array="#columns#" index="col" { // Safely grab cell using row coordinates rowStruct[col] = formatDatesToIso(arguments.input[col][arguments.input.currentRow]); } arrayAppend(queryArray, rowStruct); } return queryArray; } // 5. Return everything else untouched (Strings, Numbers, Booleans, etc.) return arguments.input; }