diff --git a/papaparse.js b/papaparse.js index b7fa8db..21c7521 100755 --- a/papaparse.js +++ b/papaparse.js @@ -203,6 +203,8 @@ } _config.dynamicTyping = dynamicTyping; + _config.transform = isFunction(_config.transform) ? _config.transform : false; + if (_config.worker && Papa.WORKERS_SUPPORTED) { var w = newWorker(); @@ -976,7 +978,7 @@ if (needsHeaderRow()) fillHeaderFields(); - return applyHeaderAndDynamicTyping(); + return applyHeaderAndDynamicTypingAndTransformation(); } function needsHeaderRow() @@ -1028,9 +1030,21 @@ return value; } - function applyHeaderAndDynamicTyping() + function parseTransform(field, value) { + if (_config.transform) { + if (_config.transform.length === 1) { + return _config.transform(value); + } else { + return _config.transform(field,value); + } + } else { + return value; + } + } + + function applyHeaderAndDynamicTypingAndTransformation() { - if (!_results || (!_config.header && !_config.dynamicTyping)) + if (!_results || (!_config.header && !_config.dynamicTyping && !_config.transform)) return _results; for (var i = 0; i < _results.data.length; i++) @@ -1046,6 +1060,7 @@ if (_config.header) field = j >= _fields.length ? '__parsed_extra' : _fields[j]; + value = parseTransform(field, value); value = parseDynamic(field, value); if (field === '__parsed_extra') diff --git a/tests/test-cases.js b/tests/test-cases.js index 773635e..0e7bdeb 100644 --- a/tests/test-cases.js +++ b/tests/test-cases.js @@ -872,6 +872,66 @@ var PARSE_TESTS = [ errors: [] } }, + { + description: "Custom transform function converts all true and false strings to booleans regardless of case", + input: '"true","false","T","F"\r\n"TRUE","FALSE","True","False"', + config: { + transform: function(value) { + if(typeof value === "string" && value.toLowerCase() === "true") return true; + if(typeof value === "string" && value.toLowerCase() === "false") return false; + return value; + } + }, + expected: { + data: [[true,false,"T","F"], [true, false, true, false]], + errors: [] + } + }, + { + description: "Custom transform function converts leading zero strings to number and empty strings to NULL", + input: '001,002,003\r\n,null,undefined', + config: { + transform: function(value) { + if ((/^\s*-?(\d*\.?\d+|\d+\.?\d*)(e[-+]?\d+)?\s*$/i).test(value)) { + return Number.parseFloat(value); + } else if (value === "") { + return null; + } + return value; + } + }, + expected: { + data: [[1,2,3], [null,"null","undefined"]], + errors: [] + } + }, + { + description: "Custom transform function uses cache to determine whether to act on column", + input: 'A,B,C\r\n1,2,3\r\n4,5,6', + config: { + transform: function(field,value) { + if (!this.transformCache) { + this.transformCache = {}; + } else if (this.transformCache[field] === true) { + return value + ".0"; + } else if (this.transformCache[field] === false) { + return value; + } + + if (field > 0) { + this.transformCache[field] = true; + return value + ".0"; + } else { + this.transformCache[field] = false; + return value; + } + } + }, + expected: { + data: [["A","B.0","C.0"], ["1","2.0","3.0"], ["4","5.0","6.0"]], + errors: [] + } + }, { description: "Blank line at beginning", input: '\r\na,b,c\r\nd,e,f',