convert-csv-to-json 4.46.0 → 4.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/csvToJson-mockup.html +309 -0
- package/index.d.ts +53 -6
- package/index.js +81 -60
- package/package.json +3 -1
- package/src/browserApi.js +39 -105
- package/src/core/configurable.js +126 -0
- package/src/{util → core}/errors.js +21 -20
- package/src/core/parserConfig.js +37 -0
- package/src/{streamProcessor.js → core/streamProcessor.js} +121 -9
- package/src/csvToJson.js +96 -181
- package/src/csvToJsonAsync.js +15 -102
- package/src/util/fileUtils.js +161 -38
- package/src/util/jsonUtils.js +1 -1
package/src/csvToJson.js
CHANGED
|
@@ -8,7 +8,9 @@ const {
|
|
|
8
8
|
ConfigurationError,
|
|
9
9
|
CsvFormatError,
|
|
10
10
|
JsonValidationError
|
|
11
|
-
} = require('./
|
|
11
|
+
} = require('./core/errors');
|
|
12
|
+
const Configurable = require('./core/configurable');
|
|
13
|
+
const ParserConfig = require('./core/parserConfig');
|
|
12
14
|
|
|
13
15
|
const DEFAULT_FIELD_DELIMITER = ",";
|
|
14
16
|
const QUOTE_CHAR = '"';
|
|
@@ -21,114 +23,52 @@ const CR = '\r';
|
|
|
21
23
|
* Provides chainable API for configuring and converting CSV data
|
|
22
24
|
* @category 2-Sync
|
|
23
25
|
*/
|
|
24
|
-
class CsvToJson {
|
|
26
|
+
class CsvToJson extends Configurable {
|
|
25
27
|
|
|
26
28
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* @param {
|
|
30
|
-
* @returns {
|
|
31
|
-
*/
|
|
32
|
-
formatValueByType(active) {
|
|
33
|
-
this.printValueFormatByType = active;
|
|
34
|
-
return this;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Enable or disable support for RFC 4180 quoted fields
|
|
39
|
-
* When enabled, fields wrapped in double quotes can contain delimiters and newlines
|
|
40
|
-
* @param {boolean} active - Whether to support quoted fields
|
|
41
|
-
* @returns {this} For method chaining
|
|
42
|
-
*/
|
|
43
|
-
supportQuotedField(active) {
|
|
44
|
-
this.isSupportQuotedField = active;
|
|
45
|
-
return this;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Set the field delimiter character
|
|
50
|
-
* @param {string} delimiter - Character(s) to use as field separator (default: ',')
|
|
51
|
-
* @returns {this} For method chaining
|
|
29
|
+
* Parse CSV content using a frozen configuration snapshot.
|
|
30
|
+
* @param {string} parsedCsv - Raw CSV content as string
|
|
31
|
+
* @param {ParserConfig} config - Frozen parser configuration
|
|
32
|
+
* @returns {Array<object>} Parsed JSON array
|
|
52
33
|
*/
|
|
53
|
-
|
|
54
|
-
this.
|
|
55
|
-
return this;
|
|
56
|
-
}
|
|
34
|
+
csvToJsonWithConfig(parsedCsv, config) {
|
|
35
|
+
this.validateInputConfig(config);
|
|
57
36
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
*/
|
|
63
|
-
trimHeaderFieldWhiteSpace(active) {
|
|
64
|
-
this.isTrimHeaderFieldWhiteSpace = active;
|
|
65
|
-
return this;
|
|
66
|
-
}
|
|
37
|
+
const records = this.parseRecords(parsedCsv);
|
|
38
|
+
const fieldDelimiter = this.getFieldDelimiter(config);
|
|
39
|
+
let index = this.getIndexHeader(config);
|
|
40
|
+
let headers;
|
|
67
41
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
indexHeader(indexHeaderValue) {
|
|
75
|
-
if (isNaN(indexHeaderValue)) {
|
|
76
|
-
throw ConfigurationError.invalidHeaderIndex(indexHeaderValue);
|
|
42
|
+
while (index < records.length) {
|
|
43
|
+
headers = this.getFields(records[index], config, fieldDelimiter);
|
|
44
|
+
if (stringUtils.hasContent(headers)) {
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
index++;
|
|
77
48
|
}
|
|
78
|
-
this.indexHeaderValue = indexHeaderValue;
|
|
79
|
-
return this;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Configure sub-array parsing for special field values
|
|
85
|
-
* Fields bracketed by delimiter and containing separator are parsed into arrays
|
|
86
|
-
* @param {string} delimiter - Bracket character (default: '*')
|
|
87
|
-
* @param {string} separator - Item separator within brackets (default: ',')
|
|
88
|
-
* @returns {this} For method chaining
|
|
89
|
-
* @example
|
|
90
|
-
* // Input: "*val1,val2,val3*"
|
|
91
|
-
* // Output: ["val1", "val2", "val3"]
|
|
92
|
-
* .parseSubArray('*', ',')
|
|
93
|
-
*/
|
|
94
|
-
parseSubArray(delimiter = '*',separator = ',') {
|
|
95
|
-
this.parseSubArrayDelimiter = delimiter;
|
|
96
|
-
this.parseSubArraySeparator = separator;
|
|
97
|
-
return this;
|
|
98
|
-
}
|
|
99
49
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
* @returns {this} For method chaining
|
|
104
|
-
*/
|
|
105
|
-
encoding(encoding){
|
|
106
|
-
this.encoding = encoding;
|
|
107
|
-
return this;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Configure columns to exclude from output
|
|
112
|
-
* @param {Array<number>} indexes - Column indexes to ignore
|
|
113
|
-
* @returns {this} For method chaining
|
|
114
|
-
* @private Used internally after validation in index.js
|
|
115
|
-
*/
|
|
116
|
-
ignoreColumnIndexes(indexes) {
|
|
117
|
-
this.indexesToIgnore = new Set(indexes);
|
|
118
|
-
return this;
|
|
119
|
-
}
|
|
50
|
+
if (!headers) {
|
|
51
|
+
throw CsvFormatError.missingHeader();
|
|
52
|
+
}
|
|
120
53
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
54
|
+
const jsonResult = [];
|
|
55
|
+
for (let i = index + 1; i < records.length; i++) {
|
|
56
|
+
const currentLine = this.getFields(records[i], config, fieldDelimiter);
|
|
57
|
+
|
|
58
|
+
if (stringUtils.hasContent(currentLine)) {
|
|
59
|
+
let row = this.buildJsonResult(headers, currentLine, config);
|
|
60
|
+
if (config.rowMapper) {
|
|
61
|
+
row = config.rowMapper(row, i - (index + 1));
|
|
62
|
+
if (row != null) {
|
|
63
|
+
jsonResult.push(row);
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
jsonResult.push(row);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
129
69
|
}
|
|
130
|
-
|
|
131
|
-
return
|
|
70
|
+
|
|
71
|
+
return jsonResult;
|
|
132
72
|
}
|
|
133
73
|
|
|
134
74
|
/**
|
|
@@ -174,7 +114,8 @@ class CsvToJson {
|
|
|
174
114
|
* console.log(rows);
|
|
175
115
|
*/
|
|
176
116
|
getJsonFromCsv(fileInputName) {
|
|
177
|
-
|
|
117
|
+
const config = this.getParserConfig();
|
|
118
|
+
const parsedCsv = fileUtils.readFile(fileInputName, config.encoding || 'utf8');
|
|
178
119
|
return this.csvToJson(parsedCsv);
|
|
179
120
|
}
|
|
180
121
|
|
|
@@ -219,58 +160,7 @@ class CsvToJson {
|
|
|
219
160
|
* @private
|
|
220
161
|
*/
|
|
221
162
|
csvToJson(parsedCsv) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
// Parse CSV into individual records, respecting quoted fields that may contain newlines
|
|
225
|
-
let records = this.parseRecords(parsedCsv);
|
|
226
|
-
|
|
227
|
-
let fieldDelimiter = this.getFieldDelimiter();
|
|
228
|
-
let index = this.getIndexHeader();
|
|
229
|
-
let headers;
|
|
230
|
-
|
|
231
|
-
// Find the header row
|
|
232
|
-
while (index < records.length) {
|
|
233
|
-
if (this.isSupportQuotedField) {
|
|
234
|
-
headers = this.split(records[index]);
|
|
235
|
-
} else {
|
|
236
|
-
headers = records[index].split(fieldDelimiter);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (stringUtils.hasContent(headers)) {
|
|
240
|
-
break;
|
|
241
|
-
}
|
|
242
|
-
index++;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
if (!headers) {
|
|
246
|
-
throw CsvFormatError.missingHeader();
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
let jsonResult = [];
|
|
250
|
-
for (let i = (index + 1); i < records.length; i++) {
|
|
251
|
-
let currentLine;
|
|
252
|
-
if (this.isSupportQuotedField) {
|
|
253
|
-
currentLine = this.split(records[i]);
|
|
254
|
-
} else {
|
|
255
|
-
currentLine = records[i].split(fieldDelimiter);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
if (stringUtils.hasContent(currentLine)) {
|
|
259
|
-
let row = this.buildJsonResult(headers, currentLine);
|
|
260
|
-
|
|
261
|
-
// Apply row mapper if defined
|
|
262
|
-
if (this.rowMapper) {
|
|
263
|
-
row = this.rowMapper(row, i - (index + 1)); // Pass row and 0-based row index
|
|
264
|
-
// If mapper returns null/undefined, skip this row (allows filtering)
|
|
265
|
-
if (row != null) {
|
|
266
|
-
jsonResult.push(row);
|
|
267
|
-
}
|
|
268
|
-
} else {
|
|
269
|
-
jsonResult.push(row);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
return jsonResult;
|
|
163
|
+
return this.csvToJsonWithConfig(parsedCsv, this.getParserConfig());
|
|
274
164
|
}
|
|
275
165
|
|
|
276
166
|
/**
|
|
@@ -353,51 +243,71 @@ class CsvToJson {
|
|
|
353
243
|
|
|
354
244
|
/**
|
|
355
245
|
* Get the configured field delimiter, or default if not set
|
|
246
|
+
* @param {ParserConfig} [config] - Parser configuration
|
|
356
247
|
* @returns {string} Field delimiter character
|
|
357
248
|
* @private
|
|
358
249
|
*/
|
|
359
|
-
getFieldDelimiter() {
|
|
360
|
-
if (
|
|
361
|
-
return
|
|
250
|
+
getFieldDelimiter(config = this.config) {
|
|
251
|
+
if (config.delimiter) {
|
|
252
|
+
return config.delimiter;
|
|
362
253
|
}
|
|
363
254
|
return DEFAULT_FIELD_DELIMITER;
|
|
364
255
|
}
|
|
365
256
|
|
|
366
257
|
/**
|
|
367
258
|
* Get the configured header row index, or default (0) if not set
|
|
259
|
+
* @param {ParserConfig} [config] - Parser configuration
|
|
368
260
|
* @returns {number} Header row index
|
|
369
261
|
* @private
|
|
370
262
|
*/
|
|
371
|
-
getIndexHeader(){
|
|
372
|
-
if(
|
|
373
|
-
|
|
263
|
+
getIndexHeader(config = this.config) {
|
|
264
|
+
if (config.indexHeaderValue !== null && !isNaN(config.indexHeaderValue)) {
|
|
265
|
+
return config.indexHeaderValue;
|
|
374
266
|
}
|
|
375
267
|
return 0;
|
|
376
268
|
}
|
|
377
269
|
|
|
270
|
+
/**
|
|
271
|
+
* Get fields for a CSV record line according to configured parser rules.
|
|
272
|
+
* Uses quoted-field splitting when RFC 4180 support is enabled.
|
|
273
|
+
* @param {string} line - CSV record line
|
|
274
|
+
* @param {ParserConfig} [config] - Parser configuration
|
|
275
|
+
* @param {string} [fieldDelimiter] - Field delimiter
|
|
276
|
+
* @returns {string[]} Parsed fields
|
|
277
|
+
* @private
|
|
278
|
+
*/
|
|
279
|
+
getFields(line, config = this.config, fieldDelimiter = this.getFieldDelimiter(config)) {
|
|
280
|
+
if (config.isSupportQuotedField) {
|
|
281
|
+
return this.split(line, config);
|
|
282
|
+
}
|
|
283
|
+
return line.split(fieldDelimiter);
|
|
284
|
+
}
|
|
285
|
+
|
|
378
286
|
/**
|
|
379
287
|
* Build a JSON object from headers and field values
|
|
380
288
|
* Applies type formatting and sub-array parsing as configured
|
|
381
289
|
* @param {string[]} headers - Array of header field names
|
|
382
290
|
* @param {string[]} currentLine - Array of field values
|
|
291
|
+
* @param {ParserConfig} [config] - Frozen parser configuration
|
|
383
292
|
* @returns {object} JSON object with header names as keys
|
|
384
293
|
* @private
|
|
385
294
|
*/
|
|
386
|
-
buildJsonResult(headers, currentLine) {
|
|
295
|
+
buildJsonResult(headers, currentLine, config = this.config) {
|
|
387
296
|
let jsonObject = {};
|
|
297
|
+
const ignoredIndexes = config.indexesToIgnore ? new Set(config.indexesToIgnore) : new Set();
|
|
388
298
|
for (let j = 0; j < headers.length; j++) {
|
|
389
|
-
if (
|
|
299
|
+
if (ignoredIndexes.has(j)) {
|
|
390
300
|
continue;
|
|
391
301
|
}
|
|
392
302
|
|
|
393
|
-
let propertyName = stringUtils.trimPropertyName(
|
|
303
|
+
let propertyName = stringUtils.trimPropertyName(config.isTrimHeaderFieldWhiteSpace, headers[j]);
|
|
394
304
|
let value = currentLine[j];
|
|
395
305
|
|
|
396
|
-
if(this.isParseSubArray(value)){
|
|
397
|
-
value = this.buildJsonSubArray(value);
|
|
306
|
+
if (this.isParseSubArray(value, config)) {
|
|
307
|
+
value = this.buildJsonSubArray(value, config);
|
|
398
308
|
}
|
|
399
309
|
|
|
400
|
-
if (
|
|
310
|
+
if (config.printValueFormatByType && !Array.isArray(value)) {
|
|
401
311
|
value = stringUtils.getValueFormatByType(currentLine[j]);
|
|
402
312
|
}
|
|
403
313
|
|
|
@@ -409,18 +319,19 @@ class CsvToJson {
|
|
|
409
319
|
/**
|
|
410
320
|
* Parse a field value into a sub-array using configured delimiter and separator
|
|
411
321
|
* @param {string} value - Field value to parse
|
|
322
|
+
* @param {ParserConfig} [config] - Frozen parser configuration
|
|
412
323
|
* @returns {Array<string|number|boolean>} Array of parsed values
|
|
413
324
|
* @private
|
|
414
325
|
*/
|
|
415
|
-
buildJsonSubArray(value) {
|
|
326
|
+
buildJsonSubArray(value, config = this.config) {
|
|
416
327
|
let extractedValues = value.substring(
|
|
417
|
-
value.indexOf(
|
|
418
|
-
value.lastIndexOf(
|
|
328
|
+
value.indexOf(config.parseSubArrayDelimiter) + 1,
|
|
329
|
+
value.lastIndexOf(config.parseSubArrayDelimiter)
|
|
419
330
|
);
|
|
420
331
|
extractedValues.trim();
|
|
421
|
-
value = extractedValues.split(
|
|
422
|
-
if(
|
|
423
|
-
for(let i=0; i < value.length; i++){
|
|
332
|
+
value = extractedValues.split(config.parseSubArraySeparator);
|
|
333
|
+
if (config.printValueFormatByType) {
|
|
334
|
+
for (let i = 0; i < value.length; i++) {
|
|
424
335
|
value[i] = stringUtils.getValueFormatByType(value[i]);
|
|
425
336
|
}
|
|
426
337
|
}
|
|
@@ -430,12 +341,13 @@ class CsvToJson {
|
|
|
430
341
|
/**
|
|
431
342
|
* Check if a field value should be parsed as a sub-array
|
|
432
343
|
* @param {string} value - Field value to check
|
|
344
|
+
* @param {ParserConfig} [config] - Frozen parser configuration
|
|
433
345
|
* @returns {boolean} True if value is bracketed with sub-array delimiter
|
|
434
346
|
* @private
|
|
435
347
|
*/
|
|
436
|
-
isParseSubArray(value){
|
|
437
|
-
if(
|
|
438
|
-
if (value && (value.indexOf(
|
|
348
|
+
isParseSubArray(value, config = this.config) {
|
|
349
|
+
if (config.parseSubArrayDelimiter) {
|
|
350
|
+
if (value && (value.indexOf(config.parseSubArrayDelimiter) === 0 && value.lastIndexOf(config.parseSubArrayDelimiter) === (value.length - 1))) {
|
|
439
351
|
return true;
|
|
440
352
|
}
|
|
441
353
|
}
|
|
@@ -444,18 +356,19 @@ class CsvToJson {
|
|
|
444
356
|
|
|
445
357
|
/**
|
|
446
358
|
* Validate configuration for conflicts and incompatibilities
|
|
359
|
+
* @param {ParserConfig} [config] - Parser configuration
|
|
447
360
|
* @throws {ConfigurationError} If incompatible options are set
|
|
448
361
|
* @private
|
|
449
362
|
*/
|
|
450
|
-
validateInputConfig(){
|
|
451
|
-
if(
|
|
452
|
-
if(this.getFieldDelimiter() === '"'){
|
|
363
|
+
validateInputConfig(config = this.config) {
|
|
364
|
+
if (config.isSupportQuotedField) {
|
|
365
|
+
if (this.getFieldDelimiter(config) === '"') {
|
|
453
366
|
throw ConfigurationError.quotedFieldConflict('fieldDelimiter', '"');
|
|
454
367
|
}
|
|
455
|
-
if(
|
|
368
|
+
if (config.parseSubArraySeparator === '"') {
|
|
456
369
|
throw ConfigurationError.quotedFieldConflict('parseSubArraySeparator', '"');
|
|
457
370
|
}
|
|
458
|
-
if(
|
|
371
|
+
if (config.parseSubArrayDelimiter === '"') {
|
|
459
372
|
throw ConfigurationError.quotedFieldConflict('parseSubArrayDelimiter', '"');
|
|
460
373
|
}
|
|
461
374
|
}
|
|
@@ -478,9 +391,10 @@ class CsvToJson {
|
|
|
478
391
|
* - Escaped quotes (double quotes within quoted fields)
|
|
479
392
|
* - Empty quoted fields
|
|
480
393
|
* @param {string} line - A single CSV record line
|
|
394
|
+
* @param {ParserConfig} [config] - Parser configuration
|
|
481
395
|
* @returns {string[]} Array of field values
|
|
482
396
|
*/
|
|
483
|
-
split(line) {
|
|
397
|
+
split(line, config = this.config) {
|
|
484
398
|
if (line.length === 0) {
|
|
485
399
|
return [];
|
|
486
400
|
}
|
|
@@ -488,7 +402,7 @@ class CsvToJson {
|
|
|
488
402
|
let fields = [];
|
|
489
403
|
let currentField = '';
|
|
490
404
|
let insideQuotes = false;
|
|
491
|
-
let delimiter = this.getFieldDelimiter();
|
|
405
|
+
let delimiter = this.getFieldDelimiter(config);
|
|
492
406
|
|
|
493
407
|
for (let i = 0; i < line.length; i++) {
|
|
494
408
|
let char = line[i];
|
|
@@ -568,3 +482,4 @@ class CsvToJson {
|
|
|
568
482
|
}
|
|
569
483
|
|
|
570
484
|
module.exports = new CsvToJson();
|
|
485
|
+
module.exports.CsvToJson = CsvToJson;
|
package/src/csvToJsonAsync.js
CHANGED
|
@@ -3,115 +3,24 @@
|
|
|
3
3
|
|
|
4
4
|
const fileUtils = require('./util/fileUtils');
|
|
5
5
|
const csvToJson = require('./csvToJson');
|
|
6
|
-
const
|
|
7
|
-
const
|
|
6
|
+
const Configurable = require('./core/configurable');
|
|
7
|
+
const { InputValidationError } = require('./core/errors');
|
|
8
|
+
const StreamProcessor = require('./core/streamProcessor');
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Asynchronous CSV to JSON converter
|
|
11
|
-
*
|
|
12
|
+
* Provides async file I/O methods and isolated parser configuration
|
|
12
13
|
* @category 3-Async
|
|
13
14
|
*/
|
|
14
|
-
class CsvToJsonAsync {
|
|
15
|
+
class CsvToJsonAsync extends Configurable {
|
|
15
16
|
/**
|
|
16
17
|
* Constructor initializes proxy to sync csvToJson instance
|
|
17
18
|
*/
|
|
18
19
|
constructor() {
|
|
19
|
-
|
|
20
|
+
super();
|
|
20
21
|
this.csvToJson = csvToJson;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
/**
|
|
24
|
-
* Enable or disable automatic type formatting for values
|
|
25
|
-
* @param {boolean} active - Whether to format values by type
|
|
26
|
-
* @returns {this} For method chaining
|
|
27
|
-
*/
|
|
28
|
-
formatValueByType(active) {
|
|
29
|
-
this.csvToJson.formatValueByType(active);
|
|
30
|
-
return this;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Enable or disable support for RFC 4180 quoted fields
|
|
35
|
-
* @param {boolean} active - Whether to support quoted fields
|
|
36
|
-
* @returns {this} For method chaining
|
|
37
|
-
*/
|
|
38
|
-
supportQuotedField(active) {
|
|
39
|
-
this.csvToJson.supportQuotedField(active);
|
|
40
|
-
return this;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Set the field delimiter character
|
|
45
|
-
* @param {string} delimiter - Character(s) to use as field separator
|
|
46
|
-
* @returns {this} For method chaining
|
|
47
|
-
*/
|
|
48
|
-
fieldDelimiter(delimiter) {
|
|
49
|
-
this.csvToJson.fieldDelimiter(delimiter);
|
|
50
|
-
return this;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Configure whitespace handling in header field names
|
|
55
|
-
* @param {boolean} active - If true, removes all whitespace; if false, only trims edges
|
|
56
|
-
* @returns {this} For method chaining
|
|
57
|
-
*/
|
|
58
|
-
trimHeaderFieldWhiteSpace(active) {
|
|
59
|
-
this.csvToJson.trimHeaderFieldWhiteSpace(active);
|
|
60
|
-
return this;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Set the row index where CSV headers are located
|
|
65
|
-
* @param {number} indexHeader - Zero-based row index containing headers
|
|
66
|
-
* @returns {this} For method chaining
|
|
67
|
-
*/
|
|
68
|
-
indexHeader(indexHeader) {
|
|
69
|
-
this.csvToJson.indexHeader(indexHeader);
|
|
70
|
-
return this;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Configure sub-array parsing for special field values
|
|
75
|
-
* @param {string} delimiter - Bracket character (default: '*')
|
|
76
|
-
* @param {string} separator - Item separator within brackets (default: ',')
|
|
77
|
-
* @returns {this} For method chaining
|
|
78
|
-
*/
|
|
79
|
-
parseSubArray(delimiter = '*', separator = ',') {
|
|
80
|
-
this.csvToJson.parseSubArray(delimiter, separator);
|
|
81
|
-
return this;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Set a mapper function to transform each row after conversion
|
|
86
|
-
* @param {function(object, number): (object|null)} mapperFn - Function receiving (row, index) that returns transformed row or null to filter
|
|
87
|
-
* @returns {this} For method chaining
|
|
88
|
-
*/
|
|
89
|
-
mapRows(mapperFn) {
|
|
90
|
-
this.csvToJson.mapRows(mapperFn);
|
|
91
|
-
return this;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Set file encoding for reading CSV files
|
|
96
|
-
* @param {string} encoding - Node.js supported encoding (e.g., 'utf8', 'latin1')
|
|
97
|
-
* @returns {this} For method chaining
|
|
98
|
-
*/
|
|
99
|
-
encoding(encoding) {
|
|
100
|
-
this.csvToJson.encoding = encoding;
|
|
101
|
-
return this;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Configure columns to exclude from output
|
|
106
|
-
* @param {Array<number>} indexes - Column indexes to ignore
|
|
107
|
-
* @returns {this} For method chaining
|
|
108
|
-
* @private Used internally after validation in index.js
|
|
109
|
-
*/
|
|
110
|
-
ignoreColumnIndexes(indexes) {
|
|
111
|
-
this.csvToJson.ignoreColumnIndexes(indexes);
|
|
112
|
-
return this;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
24
|
/**
|
|
116
25
|
* Read a CSV file and write parsed JSON to an output file (async)
|
|
117
26
|
* @param {string} fileInputName - Path to input CSV file
|
|
@@ -162,15 +71,17 @@ class CsvToJsonAsync {
|
|
|
162
71
|
);
|
|
163
72
|
}
|
|
164
73
|
|
|
74
|
+
const config = this.getParserConfig();
|
|
75
|
+
|
|
165
76
|
if (options.raw) {
|
|
166
77
|
if (inputFileNameOrCsv === '') {
|
|
167
78
|
return [];
|
|
168
79
|
}
|
|
169
|
-
return this.csvToJson.
|
|
80
|
+
return this.csvToJson.csvToJsonWithConfig(inputFileNameOrCsv, config);
|
|
170
81
|
}
|
|
171
82
|
|
|
172
|
-
const parsedCsv = await fileUtils.readFileAsync(inputFileNameOrCsv,
|
|
173
|
-
return this.csvToJson.
|
|
83
|
+
const parsedCsv = await fileUtils.readFileAsync(inputFileNameOrCsv, config.encoding || 'utf8');
|
|
84
|
+
return this.csvToJson.csvToJsonWithConfig(parsedCsv, config);
|
|
174
85
|
}
|
|
175
86
|
|
|
176
87
|
/**
|
|
@@ -205,7 +116,8 @@ class CsvToJsonAsync {
|
|
|
205
116
|
async getJsonFromStreamAsync(stream) {
|
|
206
117
|
this._validateStream(stream);
|
|
207
118
|
|
|
208
|
-
const
|
|
119
|
+
const config = this.getParserConfig();
|
|
120
|
+
const streamProcessor = new StreamProcessor(config, { isBrowser: false });
|
|
209
121
|
return streamProcessor.processStream(stream);
|
|
210
122
|
}
|
|
211
123
|
|
|
@@ -249,7 +161,8 @@ class CsvToJsonAsync {
|
|
|
249
161
|
}
|
|
250
162
|
|
|
251
163
|
const fs = require('fs');
|
|
252
|
-
const
|
|
164
|
+
const config = this.getParserConfig();
|
|
165
|
+
const encoding = typeof config.encoding === 'string' ? config.encoding : 'utf8';
|
|
253
166
|
const stream = fs.createReadStream(filePath, { encoding });
|
|
254
167
|
return this.getJsonFromStreamAsync(stream);
|
|
255
168
|
}
|