convert-csv-to-json 4.2.0 → 4.3.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/.eslintignore +3 -0
- package/.eslintrc.json +48 -0
- package/.github/workflows/ci-cd.yml +28 -2
- package/docs/api/BrowserApi.html +2435 -0
- package/docs/api/BrowserApiError.html +522 -0
- package/docs/api/ConfigurationError.html +594 -0
- package/docs/api/CsvFormatError.html +530 -0
- package/docs/api/CsvParsingError.html +384 -0
- package/docs/api/CsvToJson.html +3136 -0
- package/docs/api/CsvToJsonAsync.html +2672 -0
- package/docs/api/FileOperationError.html +270 -0
- package/docs/api/FileUtils.html +1012 -0
- package/docs/api/InputValidationError.html +293 -0
- package/docs/api/JsonUtil.html +340 -0
- package/docs/api/JsonValidationError.html +247 -0
- package/docs/api/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-Bold-webfont.svg +1830 -0
- package/docs/api/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
- package/docs/api/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-Italic-webfont.svg +1830 -0
- package/docs/api/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-Light-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-Light-webfont.svg +1831 -0
- package/docs/api/fonts/OpenSans-Light-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
- package/docs/api/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-Regular-webfont.svg +1831 -0
- package/docs/api/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/docs/api/global.html +3315 -0
- package/docs/api/index.html +326 -0
- package/docs/api/index.js.html +341 -0
- package/docs/api/scripts/linenumber.js +25 -0
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/docs/api/scripts/prettify/lang-css.js +2 -0
- package/docs/api/scripts/prettify/prettify.js +28 -0
- package/docs/api/src_browserApi.js.html +271 -0
- package/docs/api/src_csvToJson.js.html +605 -0
- package/docs/api/src_csvToJsonAsync.js.html +244 -0
- package/docs/api/src_util_errors.js.html +374 -0
- package/docs/api/src_util_fileUtils.js.html +147 -0
- package/docs/api/src_util_jsonUtils.js.html +75 -0
- package/docs/api/src_util_stringUtils.js.html +212 -0
- package/docs/api/styles/jsdoc-default.css +358 -0
- package/docs/api/styles/prettify-jsdoc.css +111 -0
- package/docs/api/styles/prettify-tomorrow.css +132 -0
- package/index.js +109 -32
- package/jsdoc.json +17 -0
- package/package.json +10 -3
- package/src/browserApi.js +96 -4
- package/src/csvToJson.js +163 -2
- package/src/csvToJsonAsync.js +74 -14
- package/src/util/errors.js +96 -0
- package/src/util/fileUtils.js +34 -0
- package/src/util/jsonUtils.js +8 -0
- package/src/util/stringUtils.js +51 -0
package/src/csvToJson.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* globals FileOperationError */
|
|
1
2
|
"use strict";
|
|
2
3
|
|
|
3
4
|
const fileUtils = require('./util/fileUtils');
|
|
@@ -15,28 +16,60 @@ const CRLF = '\r\n';
|
|
|
15
16
|
const LF = '\n';
|
|
16
17
|
const CR = '\r';
|
|
17
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Main CSV to JSON converter class
|
|
21
|
+
* Provides chainable API for configuring and converting CSV data
|
|
22
|
+
*/
|
|
18
23
|
class CsvToJson {
|
|
19
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Enable or disable automatic type formatting for values
|
|
27
|
+
* When enabled, numeric strings are converted to numbers, 'true'/'false' to booleans
|
|
28
|
+
* @param {boolean} active - Whether to format values by type
|
|
29
|
+
* @returns {this} For method chaining
|
|
30
|
+
*/
|
|
20
31
|
formatValueByType(active) {
|
|
21
32
|
this.printValueFormatByType = active;
|
|
22
33
|
return this;
|
|
23
34
|
}
|
|
24
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Enable or disable support for RFC 4180 quoted fields
|
|
38
|
+
* When enabled, fields wrapped in double quotes can contain delimiters and newlines
|
|
39
|
+
* @param {boolean} active - Whether to support quoted fields
|
|
40
|
+
* @returns {this} For method chaining
|
|
41
|
+
*/
|
|
25
42
|
supportQuotedField(active) {
|
|
26
43
|
this.isSupportQuotedField = active;
|
|
27
44
|
return this;
|
|
28
45
|
}
|
|
29
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Set the field delimiter character
|
|
49
|
+
* @param {string} delimiter - Character(s) to use as field separator (default: ',')
|
|
50
|
+
* @returns {this} For method chaining
|
|
51
|
+
*/
|
|
30
52
|
fieldDelimiter(delimiter) {
|
|
31
53
|
this.delimiter = delimiter;
|
|
32
54
|
return this;
|
|
33
55
|
}
|
|
34
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Configure whitespace handling in header field names
|
|
59
|
+
* @param {boolean} active - If true, removes all whitespace from header names; if false, only trims edges
|
|
60
|
+
* @returns {this} For method chaining
|
|
61
|
+
*/
|
|
35
62
|
trimHeaderFieldWhiteSpace(active) {
|
|
36
63
|
this.isTrimHeaderFieldWhiteSpace = active;
|
|
37
64
|
return this;
|
|
38
65
|
}
|
|
39
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Set the row index where CSV headers are located
|
|
69
|
+
* @param {number} indexHeaderValue - Zero-based row index containing headers
|
|
70
|
+
* @returns {this} For method chaining
|
|
71
|
+
* @throws {ConfigurationError} If not a valid number
|
|
72
|
+
*/
|
|
40
73
|
indexHeader(indexHeaderValue) {
|
|
41
74
|
if (isNaN(indexHeaderValue)) {
|
|
42
75
|
throw ConfigurationError.invalidHeaderIndex(indexHeaderValue);
|
|
@@ -46,11 +79,28 @@ class CsvToJson {
|
|
|
46
79
|
}
|
|
47
80
|
|
|
48
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Configure sub-array parsing for special field values
|
|
84
|
+
* Fields bracketed by delimiter and containing separator are parsed into arrays
|
|
85
|
+
* @param {string} delimiter - Bracket character (default: '*')
|
|
86
|
+
* @param {string} separator - Item separator within brackets (default: ',')
|
|
87
|
+
* @returns {this} For method chaining
|
|
88
|
+
* @example
|
|
89
|
+
* // Input: "*val1,val2,val3*"
|
|
90
|
+
* // Output: ["val1", "val2", "val3"]
|
|
91
|
+
* .parseSubArray('*', ',')
|
|
92
|
+
*/
|
|
49
93
|
parseSubArray(delimiter = '*',separator = ',') {
|
|
50
94
|
this.parseSubArrayDelimiter = delimiter;
|
|
51
95
|
this.parseSubArraySeparator = separator;
|
|
96
|
+
return this;
|
|
52
97
|
}
|
|
53
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Set file encoding for reading CSV files
|
|
101
|
+
* @param {string} encoding - Node.js supported encoding (e.g., 'utf8', 'latin1', 'ascii')
|
|
102
|
+
* @returns {this} For method chaining
|
|
103
|
+
*/
|
|
54
104
|
encoding(encoding){
|
|
55
105
|
this.encoding = encoding;
|
|
56
106
|
return this;
|
|
@@ -69,11 +119,30 @@ class CsvToJson {
|
|
|
69
119
|
return this;
|
|
70
120
|
}
|
|
71
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Read a CSV file and write the parsed JSON to an output file
|
|
124
|
+
* @param {string} fileInputName - Path to input CSV file
|
|
125
|
+
* @param {string} fileOutputName - Path to output JSON file
|
|
126
|
+
* @throws {FileOperationError} If file read or write fails
|
|
127
|
+
* @throws {CsvFormatError} If CSV is malformed
|
|
128
|
+
*/
|
|
72
129
|
generateJsonFileFromCsv(fileInputName, fileOutputName) {
|
|
73
130
|
let jsonStringified = this.getJsonFromCsvStringified(fileInputName);
|
|
74
131
|
fileUtils.writeFile(jsonStringified, fileOutputName);
|
|
75
132
|
}
|
|
76
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Read a CSV file and return parsed data as stringified JSON
|
|
136
|
+
* @param {string} fileInputName - Path to input CSV file
|
|
137
|
+
* @returns {string} JSON stringified array of objects
|
|
138
|
+
* @throws {FileOperationError} If file read fails
|
|
139
|
+
* @throws {CsvFormatError} If CSV is malformed
|
|
140
|
+
* @throws {JsonValidationError} If JSON generation fails
|
|
141
|
+
* @example
|
|
142
|
+
* const csvToJson = require('convert-csv-to-json');
|
|
143
|
+
* const jsonString = csvToJson.getJsonFromCsvStringified('resource/input.csv');
|
|
144
|
+
* console.log(jsonString);
|
|
145
|
+
*/
|
|
77
146
|
getJsonFromCsvStringified(fileInputName) {
|
|
78
147
|
let json = this.getJsonFromCsv(fileInputName);
|
|
79
148
|
let jsonStringified = JSON.stringify(json, undefined, 1);
|
|
@@ -81,15 +150,47 @@ class CsvToJson {
|
|
|
81
150
|
return jsonStringified;
|
|
82
151
|
}
|
|
83
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Read a CSV file and return parsed data as JSON array of objects
|
|
155
|
+
* @param {string} fileInputName - Path to input CSV file
|
|
156
|
+
* @returns {Array<object>} Array of objects representing CSV rows
|
|
157
|
+
* @throws {FileOperationError} If file read fails
|
|
158
|
+
* @throws {CsvFormatError} If CSV is malformed
|
|
159
|
+
* @example
|
|
160
|
+
* const csvToJson = require('convert-csv-to-json');
|
|
161
|
+
* const rows = csvToJson.getJsonFromCsv('resource/input.csv');
|
|
162
|
+
* console.log(rows);
|
|
163
|
+
*/
|
|
84
164
|
getJsonFromCsv(fileInputName) {
|
|
85
165
|
let parsedCsv = fileUtils.readFile(fileInputName, this.encoding);
|
|
86
166
|
return this.csvToJson(parsedCsv);
|
|
87
167
|
}
|
|
88
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Parse CSV string content and return as JSON array of objects
|
|
171
|
+
* @param {string} csvString - CSV content as string
|
|
172
|
+
* @returns {Array<object>} Array of objects representing CSV rows
|
|
173
|
+
* @throws {CsvFormatError} If CSV is malformed
|
|
174
|
+
* @example
|
|
175
|
+
* const csvToJson = require('convert-csv-to-json');
|
|
176
|
+
* const rows = csvToJson.csvStringToJson('name,age\nAlice,30');
|
|
177
|
+
* console.log(rows); // [{ name: 'Alice', age: '30' }]
|
|
178
|
+
*/
|
|
89
179
|
csvStringToJson(csvString) {
|
|
90
180
|
return this.csvToJson(csvString);
|
|
91
181
|
}
|
|
92
182
|
|
|
183
|
+
/**
|
|
184
|
+
* Parse CSV string content and return as stringified JSON
|
|
185
|
+
* @param {string} csvString - CSV content as string
|
|
186
|
+
* @returns {string} JSON stringified array of objects
|
|
187
|
+
* @throws {CsvFormatError} If CSV is malformed
|
|
188
|
+
* @throws {JsonValidationError} If JSON generation fails
|
|
189
|
+
* @example
|
|
190
|
+
* const csvToJson = require('convert-csv-to-json');
|
|
191
|
+
* const jsonString = csvToJson.csvStringToJsonStringified('name,age\nAlice,30');
|
|
192
|
+
* console.log(jsonString);
|
|
193
|
+
*/
|
|
93
194
|
csvStringToJsonStringified(csvString) {
|
|
94
195
|
let json = this.csvStringToJson(csvString);
|
|
95
196
|
let jsonStringified = JSON.stringify(json, undefined, 1);
|
|
@@ -97,6 +198,14 @@ class CsvToJson {
|
|
|
97
198
|
return jsonStringified;
|
|
98
199
|
}
|
|
99
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Core CSV parsing logic - converts CSV string to JSON array
|
|
203
|
+
* Handles quoted fields per RFC 4180 when configured
|
|
204
|
+
* Applies row mapping and filtering when configured
|
|
205
|
+
* @param {string} parsedCsv - Raw CSV content as string
|
|
206
|
+
* @returns {Array<object>} Array of objects with CSV data
|
|
207
|
+
* @private
|
|
208
|
+
*/
|
|
100
209
|
csvToJson(parsedCsv) {
|
|
101
210
|
this.validateInputConfig();
|
|
102
211
|
|
|
@@ -230,6 +339,11 @@ class CsvToJson {
|
|
|
230
339
|
return 0;
|
|
231
340
|
}
|
|
232
341
|
|
|
342
|
+
/**
|
|
343
|
+
* Get the configured field delimiter, or default if not set
|
|
344
|
+
* @returns {string} Field delimiter character
|
|
345
|
+
* @private
|
|
346
|
+
*/
|
|
233
347
|
getFieldDelimiter() {
|
|
234
348
|
if (this.delimiter) {
|
|
235
349
|
return this.delimiter;
|
|
@@ -237,6 +351,11 @@ class CsvToJson {
|
|
|
237
351
|
return DEFAULT_FIELD_DELIMITER;
|
|
238
352
|
}
|
|
239
353
|
|
|
354
|
+
/**
|
|
355
|
+
* Get the configured header row index, or default (0) if not set
|
|
356
|
+
* @returns {number} Header row index
|
|
357
|
+
* @private
|
|
358
|
+
*/
|
|
240
359
|
getIndexHeader(){
|
|
241
360
|
if(this.indexHeaderValue !== null && !isNaN(this.indexHeaderValue)){
|
|
242
361
|
return this.indexHeaderValue;
|
|
@@ -244,6 +363,14 @@ class CsvToJson {
|
|
|
244
363
|
return 0;
|
|
245
364
|
}
|
|
246
365
|
|
|
366
|
+
/**
|
|
367
|
+
* Build a JSON object from headers and field values
|
|
368
|
+
* Applies type formatting and sub-array parsing as configured
|
|
369
|
+
* @param {string[]} headers - Array of header field names
|
|
370
|
+
* @param {string[]} currentLine - Array of field values
|
|
371
|
+
* @returns {object} JSON object with header names as keys
|
|
372
|
+
* @private
|
|
373
|
+
*/
|
|
247
374
|
buildJsonResult(headers, currentLine) {
|
|
248
375
|
let jsonObject = {};
|
|
249
376
|
for (let j = 0; j < headers.length; j++) {
|
|
@@ -263,6 +390,12 @@ class CsvToJson {
|
|
|
263
390
|
return jsonObject;
|
|
264
391
|
}
|
|
265
392
|
|
|
393
|
+
/**
|
|
394
|
+
* Parse a field value into a sub-array using configured delimiter and separator
|
|
395
|
+
* @param {string} value - Field value to parse
|
|
396
|
+
* @returns {Array<string|number|boolean>} Array of parsed values
|
|
397
|
+
* @private
|
|
398
|
+
*/
|
|
266
399
|
buildJsonSubArray(value) {
|
|
267
400
|
let extractedValues = value.substring(
|
|
268
401
|
value.indexOf(this.parseSubArrayDelimiter) + 1,
|
|
@@ -278,6 +411,12 @@ class CsvToJson {
|
|
|
278
411
|
return value;
|
|
279
412
|
}
|
|
280
413
|
|
|
414
|
+
/**
|
|
415
|
+
* Check if a field value should be parsed as a sub-array
|
|
416
|
+
* @param {string} value - Field value to check
|
|
417
|
+
* @returns {boolean} True if value is bracketed with sub-array delimiter
|
|
418
|
+
* @private
|
|
419
|
+
*/
|
|
281
420
|
isParseSubArray(value){
|
|
282
421
|
if(this.parseSubArrayDelimiter){
|
|
283
422
|
if (value && (value.indexOf(this.parseSubArrayDelimiter) === 0 && value.lastIndexOf(this.parseSubArrayDelimiter) === (value.length - 1))) {
|
|
@@ -287,6 +426,11 @@ class CsvToJson {
|
|
|
287
426
|
return false;
|
|
288
427
|
}
|
|
289
428
|
|
|
429
|
+
/**
|
|
430
|
+
* Validate configuration for conflicts and incompatibilities
|
|
431
|
+
* @throws {ConfigurationError} If incompatible options are set
|
|
432
|
+
* @private
|
|
433
|
+
*/
|
|
290
434
|
validateInputConfig(){
|
|
291
435
|
if(this.isSupportQuotedField) {
|
|
292
436
|
if(this.getFieldDelimiter() === '"'){
|
|
@@ -301,6 +445,12 @@ class CsvToJson {
|
|
|
301
445
|
}
|
|
302
446
|
}
|
|
303
447
|
|
|
448
|
+
/**
|
|
449
|
+
* Check if a line contains quote characters
|
|
450
|
+
* @param {string} line - Line to check
|
|
451
|
+
* @returns {boolean} True if line contains quotes
|
|
452
|
+
* @private
|
|
453
|
+
*/
|
|
304
454
|
hasQuotes(line) {
|
|
305
455
|
return line.includes('"');
|
|
306
456
|
}
|
|
@@ -363,7 +513,12 @@ class CsvToJson {
|
|
|
363
513
|
|
|
364
514
|
/**
|
|
365
515
|
* Check if character at index is an escaped quote (double quote)
|
|
366
|
-
*
|
|
516
|
+
* Escaped quotes appear as "" within quoted fields per RFC 4180
|
|
517
|
+
* @param {string} line - Line being parsed
|
|
518
|
+
* @param {number} index - Character index to check
|
|
519
|
+
* @param {boolean} insideQuoted - Whether currently inside a quoted field
|
|
520
|
+
* @returns {boolean} True if character is an escaped quote
|
|
521
|
+
* @private
|
|
367
522
|
*/
|
|
368
523
|
isEscapedQuote(line, index, insideQuoted) {
|
|
369
524
|
return insideQuoted &&
|
|
@@ -373,7 +528,13 @@ class CsvToJson {
|
|
|
373
528
|
|
|
374
529
|
/**
|
|
375
530
|
* Check if this is an empty quoted field: "" before delimiter or end of line
|
|
376
|
-
* @
|
|
531
|
+
* @param {string} line - Line being parsed
|
|
532
|
+
* @param {number} index - Character index to check
|
|
533
|
+
* @param {boolean} insideQuoted - Whether currently inside a quoted field
|
|
534
|
+
* @param {string} currentField - Current field accumulation
|
|
535
|
+
* @param {string} delimiter - Field delimiter character
|
|
536
|
+
* @returns {boolean} True if this represents an empty quoted field
|
|
537
|
+
* @private
|
|
377
538
|
*/
|
|
378
539
|
isEmptyQuotedField(line, index, insideQuoted, currentField, delimiter) {
|
|
379
540
|
if (insideQuoted || currentField !== '' || index + 1 >= line.length) {
|
package/src/csvToJsonAsync.js
CHANGED
|
@@ -1,17 +1,27 @@
|
|
|
1
|
+
/* globals CsvFormatError, FileOperationError */
|
|
1
2
|
'use strict';
|
|
2
3
|
|
|
3
4
|
const fileUtils = require('./util/fileUtils');
|
|
4
5
|
const csvToJson = require('./csvToJson');
|
|
5
6
|
const { InputValidationError } = require('./util/errors');
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Asynchronous CSV to JSON converter
|
|
10
|
+
* Proxies configuration to sync instance but provides async file I/O methods
|
|
11
|
+
*/
|
|
7
12
|
class CsvToJsonAsync {
|
|
13
|
+
/**
|
|
14
|
+
* Constructor initializes proxy to sync csvToJson instance
|
|
15
|
+
*/
|
|
8
16
|
constructor() {
|
|
9
17
|
// Proxy the configuration methods to the sync instance
|
|
10
18
|
this.csvToJson = csvToJson;
|
|
11
19
|
}
|
|
12
20
|
|
|
13
21
|
/**
|
|
14
|
-
*
|
|
22
|
+
* Enable or disable automatic type formatting for values
|
|
23
|
+
* @param {boolean} active - Whether to format values by type
|
|
24
|
+
* @returns {this} For method chaining
|
|
15
25
|
*/
|
|
16
26
|
formatValueByType(active) {
|
|
17
27
|
this.csvToJson.formatValueByType(active);
|
|
@@ -19,7 +29,9 @@ class CsvToJsonAsync {
|
|
|
19
29
|
}
|
|
20
30
|
|
|
21
31
|
/**
|
|
22
|
-
*
|
|
32
|
+
* Enable or disable support for RFC 4180 quoted fields
|
|
33
|
+
* @param {boolean} active - Whether to support quoted fields
|
|
34
|
+
* @returns {this} For method chaining
|
|
23
35
|
*/
|
|
24
36
|
supportQuotedField(active) {
|
|
25
37
|
this.csvToJson.supportQuotedField(active);
|
|
@@ -27,7 +39,9 @@ class CsvToJsonAsync {
|
|
|
27
39
|
}
|
|
28
40
|
|
|
29
41
|
/**
|
|
30
|
-
* Set field delimiter
|
|
42
|
+
* Set the field delimiter character
|
|
43
|
+
* @param {string} delimiter - Character(s) to use as field separator
|
|
44
|
+
* @returns {this} For method chaining
|
|
31
45
|
*/
|
|
32
46
|
fieldDelimiter(delimiter) {
|
|
33
47
|
this.csvToJson.fieldDelimiter(delimiter);
|
|
@@ -35,7 +49,9 @@ class CsvToJsonAsync {
|
|
|
35
49
|
}
|
|
36
50
|
|
|
37
51
|
/**
|
|
38
|
-
*
|
|
52
|
+
* Configure whitespace handling in header field names
|
|
53
|
+
* @param {boolean} active - If true, removes all whitespace; if false, only trims edges
|
|
54
|
+
* @returns {this} For method chaining
|
|
39
55
|
*/
|
|
40
56
|
trimHeaderFieldWhiteSpace(active) {
|
|
41
57
|
this.csvToJson.trimHeaderFieldWhiteSpace(active);
|
|
@@ -43,7 +59,9 @@ class CsvToJsonAsync {
|
|
|
43
59
|
}
|
|
44
60
|
|
|
45
61
|
/**
|
|
46
|
-
* Set
|
|
62
|
+
* Set the row index where CSV headers are located
|
|
63
|
+
* @param {number} indexHeader - Zero-based row index containing headers
|
|
64
|
+
* @returns {this} For method chaining
|
|
47
65
|
*/
|
|
48
66
|
indexHeader(indexHeader) {
|
|
49
67
|
this.csvToJson.indexHeader(indexHeader);
|
|
@@ -51,7 +69,10 @@ class CsvToJsonAsync {
|
|
|
51
69
|
}
|
|
52
70
|
|
|
53
71
|
/**
|
|
54
|
-
*
|
|
72
|
+
* Configure sub-array parsing for special field values
|
|
73
|
+
* @param {string} delimiter - Bracket character (default: '*')
|
|
74
|
+
* @param {string} separator - Item separator within brackets (default: ',')
|
|
75
|
+
* @returns {this} For method chaining
|
|
55
76
|
*/
|
|
56
77
|
parseSubArray(delimiter = '*', separator = ',') {
|
|
57
78
|
this.csvToJson.parseSubArray(delimiter, separator);
|
|
@@ -59,7 +80,9 @@ class CsvToJsonAsync {
|
|
|
59
80
|
}
|
|
60
81
|
|
|
61
82
|
/**
|
|
62
|
-
* Set
|
|
83
|
+
* Set a mapper function to transform each row after conversion
|
|
84
|
+
* @param {Function} mapperFn - Function receiving (row, index) that returns transformed row or null to filter
|
|
85
|
+
* @returns {this} For method chaining
|
|
63
86
|
*/
|
|
64
87
|
mapRows(mapperFn) {
|
|
65
88
|
this.csvToJson.mapRows(mapperFn);
|
|
@@ -67,7 +90,9 @@ class CsvToJsonAsync {
|
|
|
67
90
|
}
|
|
68
91
|
|
|
69
92
|
/**
|
|
70
|
-
* Set encoding
|
|
93
|
+
* Set file encoding for reading CSV files
|
|
94
|
+
* @param {string} encoding - Node.js supported encoding (e.g., 'utf8', 'latin1')
|
|
95
|
+
* @returns {this} For method chaining
|
|
71
96
|
*/
|
|
72
97
|
encoding(encoding) {
|
|
73
98
|
this.csvToJson.encoding = encoding;
|
|
@@ -75,7 +100,12 @@ class CsvToJsonAsync {
|
|
|
75
100
|
}
|
|
76
101
|
|
|
77
102
|
/**
|
|
78
|
-
*
|
|
103
|
+
* Read a CSV file and write parsed JSON to an output file (async)
|
|
104
|
+
* @param {string} fileInputName - Path to input CSV file
|
|
105
|
+
* @param {string} fileOutputName - Path to output JSON file
|
|
106
|
+
* @returns {Promise<void>}
|
|
107
|
+
* @throws {FileOperationError} If file operations fail
|
|
108
|
+
* @throws {CsvFormatError} If CSV is malformed
|
|
79
109
|
*/
|
|
80
110
|
async generateJsonFileFromCsv(fileInputName, fileOutputName) {
|
|
81
111
|
const jsonStringified = await this.getJsonFromCsvStringified(fileInputName);
|
|
@@ -83,7 +113,11 @@ class CsvToJsonAsync {
|
|
|
83
113
|
}
|
|
84
114
|
|
|
85
115
|
/**
|
|
86
|
-
*
|
|
116
|
+
* Read a CSV file and return parsed data as stringified JSON (async)
|
|
117
|
+
* @param {string} fileInputName - Path to input CSV file
|
|
118
|
+
* @returns {Promise<string>} JSON stringified array of objects
|
|
119
|
+
* @throws {FileOperationError} If file read fails
|
|
120
|
+
* @throws {CsvFormatError} If CSV is malformed
|
|
87
121
|
*/
|
|
88
122
|
async getJsonFromCsvStringified(fileInputName) {
|
|
89
123
|
const json = await this.getJsonFromCsvAsync(fileInputName);
|
|
@@ -91,8 +125,19 @@ class CsvToJsonAsync {
|
|
|
91
125
|
}
|
|
92
126
|
|
|
93
127
|
/**
|
|
94
|
-
* Main async API method
|
|
95
|
-
*
|
|
128
|
+
* Main async API method for reading CSV and returning parsed JSON
|
|
129
|
+
* Supports reading from file path or parsing CSV string content
|
|
130
|
+
* @param {string} inputFileNameOrCsv - File path or CSV string content
|
|
131
|
+
* @param {object} options - Configuration options
|
|
132
|
+
* @param {boolean} options.raw - If true, treats input as CSV string; if false, reads from file
|
|
133
|
+
* @returns {Promise<Array<object>>} Array of objects representing CSV rows
|
|
134
|
+
* @throws {InputValidationError} If input is invalid
|
|
135
|
+
* @throws {FileOperationError} If file read fails
|
|
136
|
+
* @throws {CsvFormatError} If CSV is malformed
|
|
137
|
+
* @example
|
|
138
|
+
* const csvToJson = require('convert-csv-to-json');
|
|
139
|
+
* const data = await csvToJson.getJsonFromCsvAsync('resource/input.csv');
|
|
140
|
+
* console.log(data);
|
|
96
141
|
*/
|
|
97
142
|
async getJsonFromCsvAsync(inputFileNameOrCsv, options = {}) {
|
|
98
143
|
if (inputFileNameOrCsv === null || inputFileNameOrCsv === undefined) {
|
|
@@ -116,14 +161,29 @@ class CsvToJsonAsync {
|
|
|
116
161
|
}
|
|
117
162
|
|
|
118
163
|
/**
|
|
119
|
-
* Parse CSV string to JSON
|
|
164
|
+
* Parse CSV string to JSON array (async)
|
|
165
|
+
* @param {string} csvString - CSV content as string
|
|
166
|
+
* @param {object} options - Configuration options (default: { raw: true })
|
|
167
|
+
* @returns {Promise<Array<object>>} Array of objects representing CSV rows
|
|
168
|
+
* @throws {CsvFormatError} If CSV is malformed
|
|
169
|
+
* @example
|
|
170
|
+
* const csvToJson = require('convert-csv-to-json');
|
|
171
|
+
* const data = await csvToJson.csvStringToJsonAsync('name,age\nAlice,30');
|
|
172
|
+
* console.log(data);
|
|
120
173
|
*/
|
|
121
174
|
csvStringToJsonAsync(csvString, options = { raw: true }) {
|
|
122
175
|
return this.getJsonFromCsvAsync(csvString, options);
|
|
123
176
|
}
|
|
124
177
|
|
|
125
178
|
/**
|
|
126
|
-
* Parse CSV string to stringified JSON
|
|
179
|
+
* Parse CSV string to stringified JSON (async)
|
|
180
|
+
* @param {string} csvString - CSV content as string
|
|
181
|
+
* @returns {Promise<string>} JSON stringified array of objects
|
|
182
|
+
* @throws {CsvFormatError} If CSV is malformed
|
|
183
|
+
* @example
|
|
184
|
+
* const csvToJson = require('convert-csv-to-json');
|
|
185
|
+
* const jsonString = await csvToJson.csvStringToJsonStringifiedAsync('name,age\nAlice,30');
|
|
186
|
+
* console.log(jsonString);
|
|
127
187
|
*/
|
|
128
188
|
async csvStringToJsonStringifiedAsync(csvString) {
|
|
129
189
|
const json = await this.csvStringToJsonAsync(csvString);
|
package/src/util/errors.js
CHANGED
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
* Provides consistent error formatting and context
|
|
11
11
|
*/
|
|
12
12
|
class CsvParsingError extends Error {
|
|
13
|
+
/**
|
|
14
|
+
* Create a CSV parsing error
|
|
15
|
+
* @param {string} message - Error message
|
|
16
|
+
* @param {string} code - Error code for identification
|
|
17
|
+
* @param {object} context - Additional context information (default: {})
|
|
18
|
+
*/
|
|
13
19
|
constructor(message, code, context = {}) {
|
|
14
20
|
super(message);
|
|
15
21
|
this.name = 'CsvParsingError';
|
|
@@ -18,6 +24,10 @@ class CsvParsingError extends Error {
|
|
|
18
24
|
Error.captureStackTrace(this, this.constructor);
|
|
19
25
|
}
|
|
20
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Convert error to formatted string with context information
|
|
29
|
+
* @returns {string} Formatted error message including context
|
|
30
|
+
*/
|
|
21
31
|
toString() {
|
|
22
32
|
let output = `${this.name}: ${this.message}`;
|
|
23
33
|
|
|
@@ -31,6 +41,12 @@ class CsvParsingError extends Error {
|
|
|
31
41
|
return output;
|
|
32
42
|
}
|
|
33
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Format a context value for display in error message
|
|
46
|
+
* @param {*} value - Value to format
|
|
47
|
+
* @returns {string} Formatted value string
|
|
48
|
+
* @private
|
|
49
|
+
*/
|
|
34
50
|
formatValue(value) {
|
|
35
51
|
if (value === null) return 'null';
|
|
36
52
|
if (value === undefined) return 'undefined';
|
|
@@ -42,8 +58,16 @@ class CsvParsingError extends Error {
|
|
|
42
58
|
|
|
43
59
|
/**
|
|
44
60
|
* Input validation errors
|
|
61
|
+
* Thrown when function parameters don't meet expected type or value requirements
|
|
45
62
|
*/
|
|
46
63
|
class InputValidationError extends CsvParsingError {
|
|
64
|
+
/**
|
|
65
|
+
* Create an input validation error
|
|
66
|
+
* @param {string} paramName - Name of the invalid parameter
|
|
67
|
+
* @param {string} expectedType - Expected type description
|
|
68
|
+
* @param {string} receivedType - Actual type received
|
|
69
|
+
* @param {string} details - Additional error details (optional)
|
|
70
|
+
*/
|
|
47
71
|
constructor(paramName, expectedType, receivedType, details = '') {
|
|
48
72
|
const message =
|
|
49
73
|
`Invalid input: Parameter '${paramName}' is required.\n` +
|
|
@@ -61,13 +85,27 @@ class InputValidationError extends CsvParsingError {
|
|
|
61
85
|
|
|
62
86
|
/**
|
|
63
87
|
* Configuration-related errors
|
|
88
|
+
* Thrown when configuration options conflict or are invalid
|
|
64
89
|
*/
|
|
65
90
|
class ConfigurationError extends CsvParsingError {
|
|
91
|
+
/**
|
|
92
|
+
* Create a configuration error
|
|
93
|
+
* @param {string} message - Error message
|
|
94
|
+
* @param {object} conflictingOptions - Configuration options in conflict (optional)
|
|
95
|
+
*/
|
|
66
96
|
constructor(message, conflictingOptions = {}) {
|
|
67
97
|
super(message, 'CONFIGURATION_ERROR', conflictingOptions);
|
|
68
98
|
this.name = 'ConfigurationError';
|
|
69
99
|
}
|
|
70
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Create error for quoted field configuration conflict
|
|
103
|
+
* Occurs when quote character is used as delimiter while quoted fields are enabled
|
|
104
|
+
* @param {string} optionName - Name of the conflicting option
|
|
105
|
+
* @param {string} value - Value that causes the conflict
|
|
106
|
+
* @returns {ConfigurationError} Configured error instance
|
|
107
|
+
* @static
|
|
108
|
+
*/
|
|
71
109
|
static quotedFieldConflict(optionName, value) {
|
|
72
110
|
return new ConfigurationError(
|
|
73
111
|
`Configuration conflict: supportQuotedField() is enabled, but ${optionName} is set to '${value}'.\n` +
|
|
@@ -80,6 +118,13 @@ class ConfigurationError extends CsvParsingError {
|
|
|
80
118
|
);
|
|
81
119
|
}
|
|
82
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Create error for invalid header index
|
|
123
|
+
* Occurs when indexHeader() receives non-numeric value
|
|
124
|
+
* @param {*} value - Invalid header index value
|
|
125
|
+
* @returns {ConfigurationError} Configured error instance
|
|
126
|
+
* @static
|
|
127
|
+
*/
|
|
83
128
|
static invalidHeaderIndex(value) {
|
|
84
129
|
return new ConfigurationError(
|
|
85
130
|
`Invalid configuration: indexHeader() expects a numeric value.\n` +
|
|
@@ -95,13 +140,25 @@ class ConfigurationError extends CsvParsingError {
|
|
|
95
140
|
|
|
96
141
|
/**
|
|
97
142
|
* CSV parsing errors with detailed context
|
|
143
|
+
* Thrown when CSV format is invalid or malformed
|
|
98
144
|
*/
|
|
99
145
|
class CsvFormatError extends CsvParsingError {
|
|
146
|
+
/**
|
|
147
|
+
* Create a CSV format error
|
|
148
|
+
* @param {string} message - Error message
|
|
149
|
+
* @param {object} context - Additional context information (optional)
|
|
150
|
+
*/
|
|
100
151
|
constructor(message, context = {}) {
|
|
101
152
|
super(message, 'CSV_FORMAT_ERROR', context);
|
|
102
153
|
this.name = 'CsvFormatError';
|
|
103
154
|
}
|
|
104
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Create error for missing CSV header row
|
|
158
|
+
* Occurs when no valid header row is found in CSV
|
|
159
|
+
* @returns {CsvFormatError} Configured error instance
|
|
160
|
+
* @static
|
|
161
|
+
*/
|
|
105
162
|
static missingHeader() {
|
|
106
163
|
return new CsvFormatError(
|
|
107
164
|
`CSV parsing error: No header row found.\n` +
|
|
@@ -114,6 +171,13 @@ class CsvFormatError extends CsvParsingError {
|
|
|
114
171
|
);
|
|
115
172
|
}
|
|
116
173
|
|
|
174
|
+
/**
|
|
175
|
+
* Create error for mismatched quotes in CSV
|
|
176
|
+
* Occurs when quoted fields are not properly closed
|
|
177
|
+
* @param {string} location - Where the error occurred (default: 'CSV')
|
|
178
|
+
* @returns {CsvFormatError} Configured error instance
|
|
179
|
+
* @static
|
|
180
|
+
*/
|
|
117
181
|
static mismatchedQuotes(location = 'CSV') {
|
|
118
182
|
return new CsvFormatError(
|
|
119
183
|
`CSV parsing error: Mismatched quotes detected in ${location}.\n` +
|
|
@@ -135,8 +199,15 @@ class CsvFormatError extends CsvParsingError {
|
|
|
135
199
|
|
|
136
200
|
/**
|
|
137
201
|
* File operation errors
|
|
202
|
+
* Thrown when file read or write operations fail
|
|
138
203
|
*/
|
|
139
204
|
class FileOperationError extends CsvParsingError {
|
|
205
|
+
/**
|
|
206
|
+
* Create a file operation error
|
|
207
|
+
* @param {string} operation - Type of operation that failed (e.g., 'read', 'write')
|
|
208
|
+
* @param {string} filePath - Path to the file where operation failed
|
|
209
|
+
* @param {Error} originalError - The underlying error object from Node.js
|
|
210
|
+
*/
|
|
140
211
|
constructor(operation, filePath, originalError) {
|
|
141
212
|
const message =
|
|
142
213
|
`File operation error: Failed to ${operation} file.\n` +
|
|
@@ -160,8 +231,14 @@ class FileOperationError extends CsvParsingError {
|
|
|
160
231
|
|
|
161
232
|
/**
|
|
162
233
|
* JSON validation errors
|
|
234
|
+
* Thrown when parsed CSV data cannot be converted to valid JSON
|
|
163
235
|
*/
|
|
164
236
|
class JsonValidationError extends CsvParsingError {
|
|
237
|
+
/**
|
|
238
|
+
* Create a JSON validation error
|
|
239
|
+
* @param {string} csvData - The CSV data that failed validation
|
|
240
|
+
* @param {Error} originalError - The underlying JSON parsing error
|
|
241
|
+
*/
|
|
165
242
|
constructor(csvData, originalError) {
|
|
166
243
|
const message =
|
|
167
244
|
`JSON validation error: The parsed CSV data generated invalid JSON.\n` +
|
|
@@ -184,13 +261,25 @@ class JsonValidationError extends CsvParsingError {
|
|
|
184
261
|
|
|
185
262
|
/**
|
|
186
263
|
* Browser-specific errors
|
|
264
|
+
* Thrown when browser API operations fail
|
|
187
265
|
*/
|
|
188
266
|
class BrowserApiError extends CsvParsingError {
|
|
267
|
+
/**
|
|
268
|
+
* Create a browser API error
|
|
269
|
+
* @param {string} message - Error message
|
|
270
|
+
* @param {object} context - Additional context information (optional)
|
|
271
|
+
*/
|
|
189
272
|
constructor(message, context = {}) {
|
|
190
273
|
super(message, 'BROWSER_API_ERROR', context);
|
|
191
274
|
this.name = 'BrowserApiError';
|
|
192
275
|
}
|
|
193
276
|
|
|
277
|
+
/**
|
|
278
|
+
* Create error for unavailable FileReader API
|
|
279
|
+
* Occurs when browser doesn't support FileReader
|
|
280
|
+
* @returns {BrowserApiError} Configured error instance
|
|
281
|
+
* @static
|
|
282
|
+
*/
|
|
194
283
|
static fileReaderNotAvailable() {
|
|
195
284
|
return new BrowserApiError(
|
|
196
285
|
`Browser compatibility error: FileReader API is not available.\n` +
|
|
@@ -202,6 +291,13 @@ class BrowserApiError extends CsvParsingError {
|
|
|
202
291
|
);
|
|
203
292
|
}
|
|
204
293
|
|
|
294
|
+
/**
|
|
295
|
+
* Create error for file parsing failure in browser
|
|
296
|
+
* Occurs when file read or CSV parse fails
|
|
297
|
+
* @param {Error} originalError - The underlying error that occurred
|
|
298
|
+
* @returns {BrowserApiError} Configured error instance
|
|
299
|
+
* @static
|
|
300
|
+
*/
|
|
205
301
|
static parseFileError(originalError) {
|
|
206
302
|
return new BrowserApiError(
|
|
207
303
|
`Browser file parsing error: Failed to read and parse the file.\n` +
|