Socket
Socket
Sign inDemoInstall

csv-to-js-parser

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

csv-to-js-parser - npm Package Compare versions

Comparing version 1.1.4 to 2.0.0

example/test.csv

193

app.js

@@ -42,4 +42,4 @@ /*

}
data = data.split(newRow);
//Deleting last empty row
data = data.split(newRow);
i = data.length - 1;

@@ -53,2 +53,11 @@ while (data[i] === '')

let header = data[0].split(delimeter);
//Making default description
if (!description)
{
description = {};
for (let key of header)
{
description[key] = {type: 'string', order: 1};
}
}
//Deleting header from data

@@ -67,6 +76,4 @@ data.shift();

let constants = {};
let constantsIndexes = {};
let mainKey;
let arrays = {};
let constantOrder = [];
let arraysIndexes = {};

@@ -79,69 +86,129 @@ let flag = true;

if (index === -1) throw new Error('Cannnot find selected fileds in the header');
if (description[key].constant)
if (Number(description[key].order) > 0)
{
flag = false;
constants[key] = typeInitialisation(description[key].type);
constantsIndexes[key] = index;
if (description[key].mainKey) mainKey = key;
constantOrder.push({order: description[key].order, key: key});
}
else
{
arrays[key] = [];
arraysIndexes[key] = index;
}
}
if (flag) throw new Error('You must specify constant fields!');
if (!mainKey) throw new Error('You must specify mainKey field!');
//Sorting data by mainKey
if (!isSorted)
if (flag) throw new Error('You must specify at least one group field!');
//Sorting data by orders and spliting by all constants
{
function compare(index)
function compare(a, b)
{
if (a > b) return 1;
if (a === b) return 0;
return -1;
}
function compareObjectArray(key, type)
{
return function(a, b)
{
if (a[index] > b[index]) return 1;
if (a[index] === b[index]) return 0;
return -1;
};
a = convertToType(a[key], type);
b = convertToType(b[key], type);
return compare(a, b);
}
}
data = data.sort(compare(constantsIndexes[mainKey]));
//Sorting constantOrder
constantOrder = constantOrder.sort(compareObjectArray('order', 'number'));
data = [data];
for (let i = 0; i < constantOrder.length; i++)
{
let auxArr = [];
for (let j = 0; j < data.length; j++)
{
data[j] = data[j].sort(compareObjectArray(constantsIndexes[constantOrder[i].key], description[constantOrder[i].key].type));
auxArr.push(split(data[j], constantsIndexes[constantOrder[i].key]));
}
data = arrayConcat(auxArr);
}
function arrayConcat(data) //Concat arrays of arrays into one array
{
let out = [];
for (let i = 0; i < data.length; i++)
{
for (let j = 0; j < data[i].length; j++)
{
out.push(data[i][j]);
}
}
return out;
}
function split(data, columnIndex) //Splits array to blocks with equal values in specified column
{
let out = [];
let flag = true;
let index = 0;
let row = data[0];
let keyValue = row[columnIndex];
let keyValueOld = keyValue;
while (flag)
{
let auxArr = [];
while (keyValue === keyValueOld)
{
auxArr.push(row);
index++;
if (index === data.length || !data[index])
{
flag = false;
break;
}
row = data[index];
keyValue = row[columnIndex];
}
out.push(auxArr);
if (flag) keyValueOld = keyValue;
}
return out;
}
}
let index = 0;
let mainValueOld;
let mainValue;
let out = [];
let row;
flag = true;
//Converting to obj
while(flag)
if (Object.keys(arraysIndexes).length) //If we have not group columns then we need create arrays in every object. Else we need put equal rows to separate objects.
{
for (let key in arrays) arrays[key] = [];
if (index === 0)
for (let i = 0; i < data.length; i++)
{
row = data[index];
mainValueOld = row[constantsIndexes[mainKey]];
mainValue = mainValueOld;
let obj = {};
for (let key in constantsIndexes)
{
let value = data[i][0][constantsIndexes[key]];
obj[key] = convertToType(value, description[key].type);
}
for (let key in arraysIndexes)
{
obj[key] = new Array(data[i].length);
}
for (let j = 0; j < data[i].length; j++)
{
for (let key in arraysIndexes)
{
let value = data[i][j][arraysIndexes[key]];
obj[key][j] = convertToType(value, description[key].type);
}
}
out.push(obj);
}
for (let key in constants) constants[key] = row[constantsIndexes[key]];
while(mainValue === mainValueOld)
}
else
{
for (let i = 0; i < data.length; i++)
{
for (let key in arrays) arrays[key].push(convertToType(row[arraysIndexes[key]], description[key].type));
index++;
if (index === data.length || !data[index])
for (let j = 0; j < data[i].length; j++)
{
flag = false;
break;
let obj = {};
for (let key in constantsIndexes)
{
let value = data[i][j][constantsIndexes[key]];
obj[key] = convertToType(value, description[key].type);
}
out.push(obj);
}
row = data[index];
mainValue = row[constantsIndexes[mainKey]];
}
let outElement = {};
for (let key in constants) outElement[key] = convertToType(constants[key], description[key].type);
for (let key in arrays) outElement[key] = arrays[key];
out.push(outElement);
if (flag) mainValueOld = mainValue;
}
return out;

@@ -234,17 +301,31 @@

//Fill rows
for (let i = 0; i < maxArrayLength; i++)
if (maxArrayLength) //have array properties
{
for (let j = 0; j < keys.length; j++)
for (let i = 0; i < maxArrayLength; i++)
{
if (isConstant[j])
for (let j = 0; j < keys.length; j++)
{
out += elem[keys[j]].toString();
if (isConstant[j])
{
let val = elem[keys[j]];
if (val !== null) out += val.toString();
}
else
{
let val = elem[keys[j]][i];
if (val !== null) out += val.toString();
}
if (j !== keys.length - 1) out += delimeter;
}
else
{
let val = elem[keys[j]][i];
if (val !== null) out += val.toString();
}
if (j !== keys.length - 1) out += delimeter;
out += rowDelimeter;
}
}
else
{
for (let i = 0; i < keys.length; i++)
{
let val = elem[keys[i]];
if (val !== null) out += val.toString();
if (i !== keys.length - 1) out += delimeter;
}
out += rowDelimeter;

@@ -251,0 +332,0 @@ }

{
"name": "csv-to-js-parser",
"version": "1.1.4",
"version": "2.0.0",
"description": "Converting csv data into array of JavaScript objects. Can be used for relation format input tables.",

@@ -5,0 +5,0 @@ "main": "app.js",

@@ -11,4 +11,7 @@ # Преобразование данных csv в объекты JavaScript

## Пример
Пусть у нас есть таблица с покупателями и товарами, которые они заказали в магазине:
### Функция csvToObj
Пусть у нас есть таблица с покупателями и товарами, которые они заказали в магазине (Таблица 1).
**Таблица 1**
| customer_id | customer_name | customer_status | product_id | product | price | closed |

@@ -28,3 +31,3 @@ |-------------|---------------|-----------------|------------|--------------|-------|--------|

Эта таблица интересна тем, что здесь есть поля, где встречаются повторяющиеся значения. Например, customer_id будет одинаковый в первых четырёх строках, так как эти строки описывают покупки одного и того же покупателя. В таких ситуациях обычно не требуется преобразовывать каждую строку в отдельный объект JavaScript, а нужно, чтобы был один объект на одного покупателя.
Таблица 1 интересна тем, что в ней есть столбцы, в которых по строкам встречаются повторяющиеся значения. Например, customer_id будет одинаковый в первых четырёх строках, так как эти строки описывают покупки одного и того же покупателя. В таких ситуациях обычно не требуется преобразовывать каждую строку в отдельный объект JavaScript, а нужно, чтобы был один объект на одного покупателя.

@@ -72,11 +75,11 @@ Используя данный модуль, можно перевести указанную выше таблицу в массив, где каждый элемент этого массива - это объект JavaScript, описывающий параметры конкретного покупателя и его покупки.

const description =
const normal_description =
{
customer_id: {constant: true, type: 'number', mainKey: true},
product: {constant: false, type: 'string'},
product_id:{constant: false, type: 'number'},
customer_name: {constant: true, type: 'string'},
price: {constant: false, type: 'number'},
closed: {constant: false, type: 'boolean'},
customer_status: {constant: true, type: 'number'}
customer_id: {type: 'number', order: 1},
product: {type: 'string'},
product_id: {type: 'number'},
customer_name: {type: 'string', order: 2},
price: {type: 'number'},
closed: {type: 'boolean'},
customer_status: {type: 'number', order: 2}
};

@@ -88,19 +91,90 @@ let obj = csvToObj(data, ';', description);

* delimeter: разделитель столбцов во входной таблице.
* description: описание входной таблицы.
* isSorted [optional]: указывает имеет ли входная таблица отсортированные данные. Если данные во входной таблице уже отсортированы по столбцу, для которого проставлено mainKey: true в description, то в качестве параметра isSorted можно указать true и программа не будет проводить сортировку данных, что сэкономит время работы. Но если isSorted задан, а данные на самом деле не отсортированы, то это приведёт к неверному результату преобразования.
* description [optional]: описание входной таблицы.
В параметре description описывается входная таблица:
* constant: указывается является ли определённый столбец постоянным значением или массивом. В нашем примере постоянными значениями являются те столбцы, которые описывают параметры покупателей. В тоже время, столбцы, которые описывают товары - не являются константными. В результирующем объекте они будут сохранены в виде массивов.
* type: описывается тип значений столбца. Поддерживаются три варианта: "number", "string" и "boolean".
* mainKey: одно из свойств description с constant: true, должно иметь свойство mainKey: true. Это укажет программе столбец, по которому будет проводится группировка объектов. По нему же будет проводится сортировка входной таблицы.
* order: порядок группировки. Задаётся только для тех столбцов, которые нужно группировать. Таким должен быть хотя бы один столбец. Значения этого свойства показывают в каком порядке нужно группировать столбцы. Группировка идёт в порядке возрастания значения order. То есть сначала группируются столбцы с order: 1, потом внутри первой группировки группируются столбцы с order: 2 и т. д. Можно воспринимать свойство order аналогично конструкции Group By в языке SQL.
Значения столбцов с constant: true в таблице не должны изменяться если не меняется значение в столбце, для которого прописано свойство mainKey. В противном случае часть данных потеряется при преобразовании.
Если параметр description не задан, то всем столбцам входной таблицы приписывается строковый тип и группировка производится по всем столбцам. Это значит, что каждая строка входной таблицы преобразуется в отдельный объект JavaScript.
Рассмотрим другой пример, где можно лучше увидеть как работает группировка. Пусть в качестве входных данных выступает таблица 2.
**Таблица 2**
| sex | age | person_id |
|--------|-----|-----------|
| male | 30 | 1 |
| male | 30 | 2 |
| male | 30 | 3 |
| male | 31 | 4 |
| male | 31 | 4 |
| male | 31 | 5 |
| male | 31 | 5 |
| male | 31 | 6 |
| male | 32 | 7 |
| male | 32 | 7 |
| male | 32 | 8 |
| female | 30 | 9 |
| female | 30 | 9 |
| female | 30 | 10 |
| female | 30 | 10 |
| female | 31 | 11 |
| female | 31 | 12 |
| female | 33 | 13 |
| female | 33 | 14 |
| female | 33 | 14 |
Можно заметить, что в объекте, который возвращает функция csvToObj, свойства, относящиеся к товарам, содержат массивы одинаковой длины. Используя функцию combineArrays, можно преобразовать эти массивы в единственный массив объектов, что в некоторых случаях может быть более естественным представлением данных в JavaScript.
Требуется получить массив объектов JavaScript, в котором данные из таблицы 2 будут сгруппированы сначала по возрасту, а затем по полу. В этом случае description будет таким:
```javascript
const description =
{
age: {type: 'number', order: 1},
sex: {type: 'string', order: 2},
person_id: {type: 'number'}
};
```
Результат работы csvToObj будет таким:
```javascript
[
{
sex: 'female',
age: 30,
person_id: [9, 9, 10, 10]
},
{
sex: 'male',
age: 30,
person_id: [1, 2, 3]
},
{
sex: 'female',
age: 31,
person_id: [11, 12]
},
{
sex: 'male',
age: 31,
person_id: [4, 4, 5, 5, 6]
},
{
sex: 'male',
age: 32,
person_id: [7, 7, 8]
},
{
sex: 'female',
age: 33,
person_id: [13, 14, 14]
}
]
```
### Функция combineArrays
Можно заметить, что в массиве, который возвращает функция csvToObj, свойства у его элементов, относящиеся к товарам, содержат массивы одинаковой длины. Используя функцию combineArrays, можно преобразовать эти массивы в единственный массив объектов, что в некоторых случаях может быть более естественным представлением данных в JavaScript.
```javascript
const combineArrays = require('csv-to-js-parser').combineArrays;

@@ -115,3 +189,3 @@ obj = combineArrays(obj, 'products', ['product_id', 'product', 'price', 'closed'], ['product_id', 'name', 'price', 'closed']);

Результат работы функции combineArrays для нашего примера представлен ниже:
Результат работы функции combineArrays для нашего примера из таблицы 1 представлен ниже:
```javascript

@@ -201,2 +275,6 @@ [

### Функция separateArrays
Для обратного преобразования в объект с отдельными массивами можно воспользоваться функцией separateArrays.

@@ -220,2 +298,4 @@

### Сохранение в формате JSON
Для сохранения объектов, полученных в результате работы функций csvToObj или combineArrays в файл, можно воспользоваться встроенной в node.js функцией JSON.stringify();

@@ -230,2 +310,4 @@

### Функция objToCsv
Для обратного преобразования объекта в текстовый csv формат можно воспользоваться функцией objToCsv.

@@ -232,0 +314,0 @@

@@ -47,2 +47,499 @@ 'use strict';

const not_unique_csv =
`sex;age;person_id
male;30;1
male;30;3
male;31;6
male;31;4
female;31;11
male;32;7
male;31;4
female;31;12
male;31;5
male;32;7
female;30;9
female;30;10
female;30;10
male;30;2
female;33;13
female;33;14
male;32;8
female;30;9
male;31;5
female;33;14
`;
const not_unique_not_normal_csv =
`sex;age;person_id
male;30;1
male;30;3
male;31;6
male;;4
female;31;11
;32;7
male;31;4
female;31;12
male;31;5
male;32;7
female;30;9
;30;
female;30;10
male;30;2
female;33;13
female;33;14
male;32;8
female;;9
male;31;5
female;33;14
`
const not_unique_csv_sorted_1_2 =
`sex;age;person_id
female;30;9
female;30;9
female;30;10
female;30;10
male;30;1
male;30;2
male;30;3
female;31;11
female;31;12
male;31;4
male;31;4
male;31;5
male;31;5
male;31;6
male;32;7
male;32;7
male;32;8
female;33;13
female;33;14
female;33;14
`;
const not_unique_csv_sorted_3 =
`person_id;sex;age
1;male;30
2;male;30
3;male;30
4;male;31
4;male;31
5;male;31
5;male;31
6;male;31
7;male;32
7;male;32
8;male;32
9;female;30
9;female;30
10;female;30
10;female;30
11;female;31
12;female;31
13;female;33
14;female;33
14;female;33
`;
const not_unique_not_normal_csv_sorted_1_2 =
`sex;age;person_id
female;;9
male;;4
;30;
female;30;9
female;30;10
male;30;1
male;30;2
male;30;3
female;31;11
female;31;12
male;31;4
male;31;5
male;31;5
male;31;6
male;32;7
male;32;8
;32;7
female;33;13
female;33;14
female;33;14
`;
const not_unique_obj_var1 =
[
{
sex: 'female',
age: 30,
person_id: 9
},
{
sex: 'female',
age: 30,
person_id: 9
},
{
sex: 'female',
age: 30,
person_id: 10
},
{
sex: 'female',
age: 30,
person_id: 10
},
{
sex: 'male',
age: 30,
person_id: 1
},
{
sex: 'male',
age: 30,
person_id: 2
},
{
sex: 'male',
age: 30,
person_id: 3
},
{
sex: 'female',
age: 31,
person_id: 11
},
{
sex: 'female',
age: 31,
person_id: 12
},
{
sex: 'male',
age: 31,
person_id: 4
},
{
sex: 'male',
age: 31,
person_id: 4
},
{
sex: 'male',
age: 31,
person_id: 5
},
{
sex: 'male',
age: 31,
person_id: 5
},
{
sex: 'male',
age: 31,
person_id: 6
},
{
sex: 'male',
age: 32,
person_id: 7
},
{
sex: 'male',
age: 32,
person_id: 7
},
{
sex: 'male',
age: 32,
person_id: 8
},
{
sex: 'female',
age: 33,
person_id: 13
},
{
sex: 'female',
age: 33,
person_id: 14
},
{
sex: 'female',
age: 33,
person_id: 14
}
];
const not_unique_not_normal_obj_var1 =
[
{
sex: 'female',
age: null,
person_id: 9
},
{
sex: 'male',
age: null,
person_id: 4
},
{
sex: null,
age: 30,
person_id: null
},
{
sex: 'female',
age: 30,
person_id: 9
},
{
sex: 'female',
age: 30,
person_id: 10
},
{
sex: 'male',
age: 30,
person_id: 1
},
{
sex: 'male',
age: 30,
person_id: 2
},
{
sex: 'male',
age: 30,
person_id: 3
},
{
sex: 'female',
age: 31,
person_id: 11
},
{
sex: 'female',
age: 31,
person_id: 12
},
{
sex: 'male',
age: 31,
person_id: 4
},
{
sex: 'male',
age: 31,
person_id: 5
},
{
sex: 'male',
age: 31,
person_id: 5
},
{
sex: 'male',
age: 31,
person_id: 6
},
{
sex: 'male',
age: 32,
person_id: 7
},
{
sex: 'male',
age: 32,
person_id: 8
},
{
sex: null,
age: 32,
person_id: 7
},
{
sex: 'female',
age: 33,
person_id: 13
},
{
sex: 'female',
age: 33,
person_id: 14
},
{
sex: 'female',
age: 33,
person_id: 14
}
];
const not_unique_obj_var2 =
[
{
sex: 'female',
age: 30,
person_id: [9, 9, 10, 10]
},
{
sex: 'male',
age: 30,
person_id: [1, 2, 3]
},
{
sex: 'female',
age: 31,
person_id: [11, 12]
},
{
sex: 'male',
age: 31,
person_id: [4, 4, 5, 5, 6]
},
{
sex: 'male',
age: 32,
person_id: [7, 7, 8]
},
{
sex: 'female',
age: 33,
person_id: [13, 14, 14]
}
];
const not_unique_not_normal_obj_var2 =
[
{
sex: 'female',
age: null,
person_id: [9]
},
{
sex: 'male',
age: null,
person_id: [4]
},
{
sex: null,
age: 30,
person_id: [null]
},
{
sex: 'female',
age: 30,
person_id: [9, 10]
},
{
sex: 'male',
age: 30,
person_id: [1, 2, 3]
},
{
sex: 'female',
age: 31,
person_id: [11, 12]
},
{
sex: 'male',
age: 31,
person_id: [4, 5, 5, 6]
},
{
sex: 'male',
age: 32,
person_id: [7, 8]
},
{
sex: null,
age: 32,
person_id: [7]
},
{
sex: 'female',
age: 33,
person_id: [13, 14, 14]
}
];
const not_unique_obj_var3 =
[
{
person_id: 1,
sex: 'male',
age: [30]
},
{
person_id: 2,
sex: 'male',
age: [30]
},
{
person_id: 3,
sex: 'male',
age: [30]
},
{
person_id: 4,
sex: 'male',
age: [31, 31]
},
{
person_id: 5,
sex: 'male',
age: [31, 31]
},
{
person_id: 6,
sex: 'male',
age: [31]
},
{
person_id: 7,
sex: 'male',
age: [32, 32]
},
{
person_id: 8,
sex: 'male',
age: [32]
},
{
person_id: 9,
sex: 'female',
age: [30, 30]
},
{
person_id: 10,
sex: 'female',
age: [30, 30]
},
{
person_id: 11,
sex: 'female',
age: [31]
},
{
person_id: 12,
sex: 'female',
age: [31]
},
{
person_id: 13,
sex: 'female',
age: [33]
},
{
person_id: 14,
sex: 'female',
age: [33, 33]
}
];
const normal_obj =

@@ -77,3 +574,3 @@ [

}
]
];

@@ -109,3 +606,3 @@ const not_normal_obj =

}
]
];

@@ -193,18 +690,39 @@ const normal_obj_with_combine_arrays =

}
]
];
const description =
{
customer_id: {constant: true, type: 'number', mainKey: true},
product: {constant: false, type: 'string'},
product_id:{constant: false, type: 'number'},
customer_name: {constant: true, type: 'string'},
price: {constant: false, type: 'number'},
closed: {constant: false, type: 'boolean'},
customer_status: {constant: true, type: 'number'}
};
const normal_description =
{
customer_id: {type: 'number', order: 1},
product: {type: 'string'},
product_id: {type: 'number'},
customer_name: {type: 'string', order: 2},
price: {type: 'number'},
closed: {type: 'boolean'},
customer_status: {type: 'number', order: 2}
};
const not_unique_description_var1 =
{
age: {type: 'number', order: 1},
sex: {type: 'string', order: 2},
person_id: {type: 'number', order: 3}
};
const not_unique_description_var2 =
{
age: {type: 'number', order: 1},
sex: {type: 'string', order: 2},
person_id: {type: 'number'}
};
const not_unique_description_var3 =
{
age: {type: 'number'},
sex: {type: 'string', order: 2},
person_id: {type: 'number', order: 1}
};
describe('Tests for csvToObj convertion', () =>
{
function doTest(csv, expected)
function doTest(csv, expected, description)
{

@@ -215,4 +733,23 @@ const result = app.csvToObj(csv, ';', description);

}
it ('should return normal object', () => doTest(normal_csv, normal_obj));
it ('should return not_normal object', () => doTest(not_normal_csv, not_normal_obj));
it ('should return normal object', () => doTest(normal_csv, normal_obj, normal_description));
it ('should return not_normal object', () => doTest(not_normal_csv, not_normal_obj, normal_description));
it ('should return not_unique_obj_var1 object', () => doTest(not_unique_csv, not_unique_obj_var1, not_unique_description_var1));
it ('should return not_unique_obj_var2 object', () => doTest(not_unique_csv, not_unique_obj_var2, not_unique_description_var2));
it ('should return not_unique_obj_var3 object', () => doTest(not_unique_csv, not_unique_obj_var3, not_unique_description_var3));
it ('should return not_unique_obj_var1 object (no description)', () =>
{
//Convert all properties of not_unique_description_var1 to String
let obj = new Array(not_unique_description_var1.length);
for (let i = 0; i < obj.length; i++)
{
obj[i] = {};
for (let key in not_unique_description_var1[i])
{
obj[i][key] = String(not_unique_description_var1[i][key]);
}
}
doTest(not_unique_csv, obj);
});
it('should return not_unique_not_normal_obj_var1 object', () => doTest(not_unique_not_normal_csv, not_unique_not_normal_obj_var1, not_unique_description_var1));
it('should return not_unique_not_normal_obj_var2 object', () => doTest(not_unique_not_normal_csv, not_unique_not_normal_obj_var2, not_unique_description_var2));
});

@@ -231,2 +768,7 @@

it('should return not_normal_csv_sorted', () => doTest(not_normal_obj, not_normal_csv_sorted));
it('should return not_unique_csv_sorted_1_2 (var 1)', () => doTest(not_unique_obj_var1, not_unique_csv_sorted_1_2));
it('should return not_unique_csv_sorted_1_2 (var 2)', () => doTest(not_unique_obj_var2, not_unique_csv_sorted_1_2));
it('should return not_unique_csv_sorted_3 (var 3)', () => doTest(not_unique_obj_var3, not_unique_csv_sorted_3));
it('should return not_unique_not_normal_csv_sorted_1_2 (var 1)', () => doTest(not_unique_not_normal_obj_var1, not_unique_not_normal_csv_sorted_1_2));
it('should return not_unique_not_normal_csv_sorted_2 (var 3)', () => doTest(not_unique_not_normal_obj_var2, not_unique_not_normal_csv_sorted_1_2));
});

@@ -233,0 +775,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc