convert-csv-to-json 3.12.1 → 3.13.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 CHANGED
@@ -221,13 +221,49 @@ If the header is not on the first line you can define the header index like:
221
221
  Empty rows are ignored and not parsed.
222
222
 
223
223
  #### Format property value by type
224
- If you want that a number will be printed as a Number type, and values *true* or *false* is printed as a boolean Type, use:
224
+ The `formatValueByType()` function intelligently converts string values to their appropriate types while preserving data integrity. To enable automatic type conversion:
225
+
225
226
  ```js
226
- csvToJson.formatValueByType()
227
- .getJsonFromCsv(fileInputName);
227
+ csvToJson.formatValueByType()
228
+ .getJsonFromCsv(fileInputName);
229
+ ```
230
+
231
+ This conversion follows these rules:
232
+
233
+ ##### Numbers
234
+ - Regular integers and decimals are converted to Number type
235
+ - Numbers with leading zeros are preserved as strings (e.g., "0012" stays "0012")
236
+ - Large integers outside JavaScript's safe range are preserved as strings
237
+ - Valid decimal numbers are converted to Number type
238
+
239
+ For example:
240
+ ```json
241
+ {
242
+ "normalInteger": 42, // Converted to number
243
+ "decimal": 3.14, // Converted to number
244
+ "leadingZeros": "0012345", // Kept as string to preserve leading zeros
245
+ "largeNumber": "9007199254740992" // Kept as string to preserve precision
246
+ }
247
+ ```
248
+
249
+ ##### Boolean
250
+ Case-insensitive "true" or "false" strings are converted to boolean values:
251
+ ```json
252
+ {
253
+ "registered": true, // From "true" or "TRUE" or "True"
254
+ "active": false // From "false" or "FALSE" or "False"
255
+ }
256
+ ```
257
+
258
+ ##### Complete Example
259
+ Input CSV:
260
+ ```csv
261
+ first_name;last_name;email;gender;age;id;zip;registered
262
+ Constantin;Langsdon;clangsdon0@hc360.com;Male;96;00123;123;true
263
+ Norah;Raison;nraison1@wired.com;Female;32;987;00456;FALSE
228
264
  ```
229
- For example:
230
265
 
266
+ Output JSON:
231
267
  ```json
232
268
  [
233
269
  {
@@ -236,8 +272,9 @@ For example:
236
272
  "email": "clangsdon0@hc360.com",
237
273
  "gender": "Male",
238
274
  "age": 96,
239
- "zip": 123,
240
- "registered": true
275
+ "id": "00123", // Preserved leading zeros
276
+ "zip": 123, // Converted to number
277
+ "registered": true // Converted to boolean
241
278
  },
242
279
  {
243
280
  "first_name": "Norah",
@@ -245,29 +282,12 @@ For example:
245
282
  "email": "nraison1@wired.com",
246
283
  "gender": "Female",
247
284
  "age": 32,
248
- "zip": "",
249
- "registered": false
285
+ "id": "987",
286
+ "zip": "00456", // Preserved leading zeros
287
+ "registered": false // Case-insensitive boolean conversion
250
288
  }
251
289
  ]
252
290
  ```
253
- ##### Number
254
- The property **age** is printed as
255
- ```json
256
- "age": 32
257
- ```
258
- instead of
259
- ```json
260
- "age": "32"
261
- ```
262
- ##### Boolean
263
- The property **registered** is printed as
264
- ```json
265
- "registered": true
266
- ```
267
- instead of
268
- ```json
269
- "registered": "true"
270
- ```
271
291
 
272
292
  #### Encoding
273
293
  You can read and decode files with the following encoding:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "convert-csv-to-json",
3
- "version": "3.12.1",
3
+ "version": "3.13.0",
4
4
  "description": "Convert CSV to JSON",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -1,40 +1,109 @@
1
1
  'use strict';
2
2
 
3
3
  class StringUtils {
4
+ // Regular expressions as constants for better maintainability
5
+ static PATTERNS = {
6
+ INTEGER: /^-?\d+$/,
7
+ FLOAT: /^-?\d*\.\d+$/,
8
+ WHITESPACE: /\s/g
9
+ };
4
10
 
5
- trimPropertyName(isTrimHeaderFieldWhiteSpace,value) {
6
- if(isTrimHeaderFieldWhiteSpace) {
7
- return value.replace(/\s/g, '');
11
+ static BOOLEAN_VALUES = {
12
+ TRUE: 'true',
13
+ FALSE: 'false'
14
+ };
15
+
16
+ /**
17
+ * Removes whitespace from property names based on configuration
18
+ * @param {boolean} shouldTrimAll - If true, removes all whitespace, otherwise only trims edges
19
+ * @param {string} propertyName - The property name to process
20
+ * @returns {string} The processed property name
21
+ */
22
+ trimPropertyName(shouldTrimAll, propertyName) {
23
+ if (!propertyName) {
24
+ return '';
8
25
  }
9
- return value.trim();
10
-
26
+ return shouldTrimAll ?
27
+ propertyName.replace(StringUtils.PATTERNS.WHITESPACE, '') :
28
+ propertyName.trim();
11
29
  }
12
30
 
31
+ /**
32
+ * Converts a string value to its appropriate type while preserving data integrity
33
+ * @param {string} value - The input value to convert
34
+ * @returns {string|number|boolean} The converted value
35
+ */
13
36
  getValueFormatByType(value) {
14
- if(value === undefined || value === ''){
37
+ if (this.isEmpty(value)) {
15
38
  return String();
16
39
  }
17
- //is Number
18
- let isNumber = !isNaN(value);
19
- if (isNumber) {
20
- return Number(value);
40
+
41
+ if (this.isBoolean(value)) {
42
+ return this.convertToBoolean(value);
43
+ }
44
+
45
+ if (this.isInteger(value)) {
46
+ return this.convertInteger(value);
21
47
  }
22
- // is Boolean
23
- if(value === "true" || value === "false"){
24
- return JSON.parse(value.toLowerCase());
48
+
49
+ if (this.isFloat(value)) {
50
+ return this.convertFloat(value);
25
51
  }
52
+
26
53
  return String(value);
27
54
  }
28
55
 
29
- hasContent(values) {
30
- if (values.length > 0) {
31
- for (let i = 0; i < values.length; i++) {
32
- if (values[i]) {
33
- return true;
34
- }
35
- }
56
+ /**
57
+ * Checks if a value array contains any non-empty values
58
+ * @param {Array} values - Array to check for content
59
+ * @returns {boolean} True if array has any non-empty values
60
+ */
61
+ hasContent(values = []) {
62
+ return Array.isArray(values) &&
63
+ values.some(value => Boolean(value));
64
+ }
65
+
66
+ // Private helper methods for type checking and conversion
67
+ isEmpty(value) {
68
+ return value === undefined || value === '';
69
+ }
70
+
71
+ isBoolean(value) {
72
+ const normalizedValue = value.toLowerCase();
73
+ return normalizedValue === StringUtils.BOOLEAN_VALUES.TRUE ||
74
+ normalizedValue === StringUtils.BOOLEAN_VALUES.FALSE;
75
+ }
76
+
77
+ isInteger(value) {
78
+ return StringUtils.PATTERNS.INTEGER.test(value);
79
+ }
80
+
81
+ isFloat(value) {
82
+ return StringUtils.PATTERNS.FLOAT.test(value);
83
+ }
84
+
85
+ hasLeadingZero(value) {
86
+ const isPositiveWithLeadingZero = value.length > 1 && value[0] === '0';
87
+ const isNegativeWithLeadingZero = value.length > 2 && value[0] === '-' && value[1] === '0';
88
+ return isPositiveWithLeadingZero || isNegativeWithLeadingZero;
89
+ }
90
+
91
+ convertToBoolean(value) {
92
+ return JSON.parse(value.toLowerCase());
93
+ }
94
+
95
+ convertInteger(value) {
96
+ if (this.hasLeadingZero(value)) {
97
+ return String(value);
36
98
  }
37
- return false;
99
+
100
+ const num = Number(value);
101
+ return Number.isSafeInteger(num) ? num : String(value);
102
+ }
103
+
104
+ convertFloat(value) {
105
+ const num = Number(value);
106
+ return Number.isFinite(num) ? num : String(value);
38
107
  }
39
108
  }
40
109