jtcsv 2.2.7 → 3.0.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 +31 -1
- package/bin/jtcsv.js +891 -821
- package/bin/jtcsv.ts +2534 -0
- package/csv-to-json.js +168 -145
- package/dist/jtcsv-core.cjs.js +1407 -0
- package/dist/jtcsv-core.cjs.js.map +1 -0
- package/dist/jtcsv-core.esm.js +1379 -0
- package/dist/jtcsv-core.esm.js.map +1 -0
- package/dist/jtcsv-core.umd.js +1413 -0
- package/dist/jtcsv-core.umd.js.map +1 -0
- package/dist/jtcsv-full.cjs.js +1912 -0
- package/dist/jtcsv-full.cjs.js.map +1 -0
- package/dist/jtcsv-full.esm.js +1880 -0
- package/dist/jtcsv-full.esm.js.map +1 -0
- package/dist/jtcsv-full.umd.js +1918 -0
- package/dist/jtcsv-full.umd.js.map +1 -0
- package/dist/jtcsv-workers.esm.js +759 -0
- package/dist/jtcsv-workers.esm.js.map +1 -0
- package/dist/jtcsv-workers.umd.js +773 -0
- package/dist/jtcsv-workers.umd.js.map +1 -0
- package/dist/jtcsv.cjs.js +61 -19
- package/dist/jtcsv.cjs.js.map +1 -1
- package/dist/jtcsv.esm.js +61 -19
- package/dist/jtcsv.esm.js.map +1 -1
- package/dist/jtcsv.umd.js +61 -19
- package/dist/jtcsv.umd.js.map +1 -1
- package/errors.js +188 -2
- package/examples/advanced/conditional-transformations.js +446 -0
- package/examples/advanced/conditional-transformations.ts +446 -0
- package/examples/advanced/csv-parser.worker.js +89 -0
- package/examples/advanced/csv-parser.worker.ts +89 -0
- package/examples/advanced/nested-objects-example.js +306 -0
- package/examples/advanced/nested-objects-example.ts +306 -0
- package/examples/advanced/performance-optimization.js +504 -0
- package/examples/advanced/performance-optimization.ts +504 -0
- package/examples/advanced/run-demo-server.js +116 -0
- package/examples/advanced/run-demo-server.ts +116 -0
- package/examples/advanced/web-worker-usage.html +874 -0
- package/examples/async-multithreaded-example.ts +335 -0
- package/examples/cli-advanced-usage.md +288 -0
- package/examples/cli-batch-processing.ts +38 -0
- package/examples/cli-tool.js +0 -3
- package/examples/cli-tool.ts +183 -0
- package/examples/error-handling.js +21 -7
- package/examples/error-handling.ts +356 -0
- package/examples/express-api.js +0 -3
- package/examples/express-api.ts +164 -0
- package/examples/large-dataset-example.js +0 -3
- package/examples/large-dataset-example.ts +204 -0
- package/examples/ndjson-processing.js +1 -1
- package/examples/ndjson-processing.ts +456 -0
- package/examples/plugin-excel-exporter.js +3 -4
- package/examples/plugin-excel-exporter.ts +406 -0
- package/examples/react-integration.tsx +637 -0
- package/examples/schema-validation.ts +640 -0
- package/examples/simple-usage.js +254 -254
- package/examples/simple-usage.ts +194 -0
- package/examples/streaming-example.js +4 -5
- package/examples/streaming-example.ts +419 -0
- package/examples/web-workers-advanced.ts +28 -0
- package/index.d.ts +1 -3
- package/index.js +15 -1
- package/json-save.js +9 -3
- package/json-to-csv.js +168 -21
- package/package.json +69 -10
- package/plugins/express-middleware/README.md +21 -2
- package/plugins/express-middleware/example.js +3 -4
- package/plugins/express-middleware/example.ts +135 -0
- package/plugins/express-middleware/index.d.ts +1 -1
- package/plugins/express-middleware/index.js +270 -118
- package/plugins/express-middleware/index.ts +557 -0
- package/plugins/fastify-plugin/index.js +2 -4
- package/plugins/fastify-plugin/index.ts +443 -0
- package/plugins/hono/index.ts +226 -0
- package/plugins/nestjs/index.ts +201 -0
- package/plugins/nextjs-api/examples/ConverterComponent.tsx +386 -0
- package/plugins/nextjs-api/examples/api-convert.js +0 -2
- package/plugins/nextjs-api/examples/api-convert.ts +67 -0
- package/plugins/nextjs-api/index.tsx +339 -0
- package/plugins/nextjs-api/route.js +2 -3
- package/plugins/nextjs-api/route.ts +370 -0
- package/plugins/nuxt/index.ts +94 -0
- package/plugins/nuxt/runtime/composables/useJtcsv.ts +100 -0
- package/plugins/nuxt/runtime/plugin.ts +71 -0
- package/plugins/remix/index.js +1 -1
- package/plugins/remix/index.ts +260 -0
- package/plugins/sveltekit/index.js +1 -1
- package/plugins/sveltekit/index.ts +301 -0
- package/plugins/trpc/index.ts +267 -0
- package/src/browser/browser-functions.ts +402 -0
- package/src/browser/core.js +92 -0
- package/src/browser/core.ts +152 -0
- package/src/browser/csv-to-json-browser.d.ts +3 -0
- package/src/browser/csv-to-json-browser.js +36 -14
- package/src/browser/csv-to-json-browser.ts +264 -0
- package/src/browser/errors-browser.ts +303 -0
- package/src/browser/extensions/plugins.js +92 -0
- package/src/browser/extensions/plugins.ts +93 -0
- package/src/browser/extensions/workers.js +39 -0
- package/src/browser/extensions/workers.ts +39 -0
- package/src/browser/globals.d.ts +5 -0
- package/src/browser/index.ts +192 -0
- package/src/browser/json-to-csv-browser.d.ts +3 -0
- package/src/browser/json-to-csv-browser.js +13 -3
- package/src/browser/json-to-csv-browser.ts +262 -0
- package/src/browser/streams.js +12 -2
- package/src/browser/streams.ts +336 -0
- package/src/browser/workers/csv-parser.worker.ts +377 -0
- package/src/browser/workers/worker-pool.ts +548 -0
- package/src/core/delimiter-cache.js +22 -8
- package/src/core/delimiter-cache.ts +310 -0
- package/src/core/node-optimizations.ts +449 -0
- package/src/core/plugin-system.js +29 -11
- package/src/core/plugin-system.ts +400 -0
- package/src/core/transform-hooks.ts +558 -0
- package/src/engines/fast-path-engine-new.ts +347 -0
- package/src/engines/fast-path-engine.ts +854 -0
- package/src/errors.ts +72 -0
- package/src/formats/ndjson-parser.ts +469 -0
- package/src/formats/tsv-parser.ts +334 -0
- package/src/index-with-plugins.js +16 -9
- package/src/index-with-plugins.ts +395 -0
- package/src/types/index.ts +255 -0
- package/src/utils/bom-utils.js +259 -0
- package/src/utils/bom-utils.ts +373 -0
- package/src/utils/encoding-support.js +124 -0
- package/src/utils/encoding-support.ts +155 -0
- package/src/utils/schema-validator.js +19 -19
- package/src/utils/schema-validator.ts +819 -0
- package/src/utils/transform-loader.js +1 -1
- package/src/utils/transform-loader.ts +389 -0
- package/src/utils/zod-adapter.js +170 -0
- package/src/utils/zod-adapter.ts +280 -0
- package/src/web-server/index.js +10 -10
- package/src/web-server/index.ts +683 -0
- package/src/workers/csv-multithreaded.ts +310 -0
- package/src/workers/csv-parser.worker.ts +227 -0
- package/src/workers/worker-pool.ts +409 -0
- package/stream-csv-to-json.js +26 -8
- package/stream-json-to-csv.js +1 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Пример обработки вложенных объектов в jtcsv
|
|
3
|
+
* Демонстрирует улучшенную поддержку сложных JSON структур
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { jsonToCsv, preprocessData, deepUnwrap } = require('../../index');
|
|
7
|
+
|
|
8
|
+
// Пример 1: Простые вложенные объекты
|
|
9
|
+
const simpleNestedData = [
|
|
10
|
+
{
|
|
11
|
+
id: 1,
|
|
12
|
+
name: 'John Doe',
|
|
13
|
+
profile: {
|
|
14
|
+
age: 30,
|
|
15
|
+
email: 'john@example.com',
|
|
16
|
+
address: {
|
|
17
|
+
city: 'New York',
|
|
18
|
+
country: 'USA'
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
tags: ['developer', 'javascript', 'nodejs']
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 2,
|
|
25
|
+
name: 'Jane Smith',
|
|
26
|
+
profile: {
|
|
27
|
+
age: 25,
|
|
28
|
+
email: 'jane@example.com',
|
|
29
|
+
address: {
|
|
30
|
+
city: 'London',
|
|
31
|
+
country: 'UK'
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
tags: ['designer', 'ui', 'ux']
|
|
35
|
+
}
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
console.log('=== Пример 1: Простые вложенные объекты ===\n');
|
|
39
|
+
|
|
40
|
+
// Текущая реализация (deepUnwrap)
|
|
41
|
+
console.log('Текущая реализация (deepUnwrap):');
|
|
42
|
+
const processed1 = preprocessData(simpleNestedData);
|
|
43
|
+
console.log('Обработанные данные:', JSON.stringify(processed1, null, 2));
|
|
44
|
+
|
|
45
|
+
const csv1 = jsonToCsv(processed1);
|
|
46
|
+
console.log('\nCSV результат:');
|
|
47
|
+
console.log(csv1);
|
|
48
|
+
|
|
49
|
+
// Пример 2: Сложные вложенные структуры
|
|
50
|
+
const complexNestedData = [
|
|
51
|
+
{
|
|
52
|
+
orderId: 'ORD-001',
|
|
53
|
+
customer: {
|
|
54
|
+
id: 'CUST-001',
|
|
55
|
+
name: 'Acme Corp',
|
|
56
|
+
contact: {
|
|
57
|
+
primary: {
|
|
58
|
+
name: 'Alice Johnson',
|
|
59
|
+
phone: '+1-555-1234',
|
|
60
|
+
email: 'alice@acme.com'
|
|
61
|
+
},
|
|
62
|
+
secondary: {
|
|
63
|
+
name: 'Bob Smith',
|
|
64
|
+
phone: '+1-555-5678',
|
|
65
|
+
email: 'bob@acme.com'
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
items: [
|
|
70
|
+
{
|
|
71
|
+
productId: 'PROD-001',
|
|
72
|
+
name: 'Laptop',
|
|
73
|
+
quantity: 2,
|
|
74
|
+
price: 999.99,
|
|
75
|
+
specifications: {
|
|
76
|
+
cpu: 'Intel i7',
|
|
77
|
+
ram: '16GB',
|
|
78
|
+
storage: '512GB SSD'
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
productId: 'PROD-002',
|
|
83
|
+
name: 'Mouse',
|
|
84
|
+
quantity: 1,
|
|
85
|
+
price: 49.99
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
metadata: {
|
|
89
|
+
createdAt: '2024-01-15T10:30:00Z',
|
|
90
|
+
updatedAt: '2024-01-16T14:45:00Z',
|
|
91
|
+
status: 'completed',
|
|
92
|
+
notes: ['Urgent delivery', 'Gift wrapping requested']
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
console.log('\n\n=== Пример 2: Сложные вложенные структуры ===\n');
|
|
98
|
+
|
|
99
|
+
console.log('Текущая реализация (ограничения):');
|
|
100
|
+
const processed2 = preprocessData(complexNestedData);
|
|
101
|
+
console.log('Обработанные данные (первые 500 символов):');
|
|
102
|
+
console.log(JSON.stringify(processed2, null, 2).substring(0, 500) + '...');
|
|
103
|
+
|
|
104
|
+
// Пример 3: Предлагаемые улучшения
|
|
105
|
+
console.log('\n\n=== Пример 3: Предлагаемые улучшения ===\n');
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Улучшенная функция flattenObject для автоматического разворачивания вложенных структур
|
|
109
|
+
*/
|
|
110
|
+
function flattenObject(obj, prefix = '', separator = '.', maxDepth = 3, currentDepth = 0) {
|
|
111
|
+
if (currentDepth >= maxDepth) {
|
|
112
|
+
return { [prefix || 'value']: JSON.stringify(obj) };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const result = {};
|
|
116
|
+
|
|
117
|
+
for (const key in obj) {
|
|
118
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
119
|
+
const value = obj[key];
|
|
120
|
+
const newKey = prefix ? `${prefix}${separator}${key}` : key;
|
|
121
|
+
|
|
122
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
123
|
+
// Рекурсивно разворачиваем объекты
|
|
124
|
+
const flattened = flattenObject(
|
|
125
|
+
value,
|
|
126
|
+
newKey,
|
|
127
|
+
separator,
|
|
128
|
+
maxDepth,
|
|
129
|
+
currentDepth + 1
|
|
130
|
+
);
|
|
131
|
+
Object.assign(result, flattened);
|
|
132
|
+
} else if (Array.isArray(value)) {
|
|
133
|
+
// Обработка массивов
|
|
134
|
+
if (value.length === 0) {
|
|
135
|
+
result[newKey] = '';
|
|
136
|
+
} else if (value.every(item => typeof item === 'string' || typeof item === 'number')) {
|
|
137
|
+
// Простые массивы - объединяем через запятую
|
|
138
|
+
result[newKey] = value.join(', ');
|
|
139
|
+
} else {
|
|
140
|
+
// Сложные массивы - сериализуем
|
|
141
|
+
result[newKey] = JSON.stringify(value);
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
// Примитивные значения
|
|
145
|
+
result[newKey] = value;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Улучшенная функция preprocessData с поддержкой flattening
|
|
155
|
+
*/
|
|
156
|
+
function preprocessDataWithFlattening(data, options = {}) {
|
|
157
|
+
const {
|
|
158
|
+
flatten = false,
|
|
159
|
+
separator = '.',
|
|
160
|
+
maxDepth = 3,
|
|
161
|
+
arrayHandling = 'stringify' // 'stringify', 'join', 'expand'
|
|
162
|
+
} = options;
|
|
163
|
+
|
|
164
|
+
if (!Array.isArray(data)) {
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return data.map(item => {
|
|
169
|
+
if (!item || typeof item !== 'object') {
|
|
170
|
+
return {};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (flatten) {
|
|
174
|
+
return flattenObject(item, '', separator, maxDepth);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Стандартная обработка (совместимость)
|
|
178
|
+
const processed = {};
|
|
179
|
+
for (const key in item) {
|
|
180
|
+
if (Object.prototype.hasOwnProperty.call(item, key)) {
|
|
181
|
+
const value = item[key];
|
|
182
|
+
if (value && typeof value === 'object') {
|
|
183
|
+
processed[key] = deepUnwrap(value);
|
|
184
|
+
} else {
|
|
185
|
+
processed[key] = value;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return processed;
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Демонстрация улучшенной обработки
|
|
194
|
+
console.log('Улучшенная обработка с flattening:');
|
|
195
|
+
const flattened = preprocessDataWithFlattening(simpleNestedData, { flatten: true });
|
|
196
|
+
console.log('Развернутые данные:');
|
|
197
|
+
console.log(JSON.stringify(flattened, null, 2));
|
|
198
|
+
|
|
199
|
+
const csvFlattened = jsonToCsv(flattened);
|
|
200
|
+
console.log('\nCSV с развернутыми полями:');
|
|
201
|
+
console.log(csvFlattened);
|
|
202
|
+
|
|
203
|
+
// Пример 4: Разные стратегии обработки массивов
|
|
204
|
+
console.log('\n\n=== Пример 4: Обработка массивов ===\n');
|
|
205
|
+
|
|
206
|
+
const arrayData = [
|
|
207
|
+
{
|
|
208
|
+
id: 1,
|
|
209
|
+
name: 'Product A',
|
|
210
|
+
categories: ['Electronics', 'Computers', 'Laptops'],
|
|
211
|
+
reviews: [
|
|
212
|
+
{ user: 'Alice', rating: 5, comment: 'Great product!' },
|
|
213
|
+
{ user: 'Bob', rating: 4, comment: 'Good value' }
|
|
214
|
+
],
|
|
215
|
+
attributes: {
|
|
216
|
+
colors: ['Black', 'Silver', 'Space Gray'],
|
|
217
|
+
sizes: ['13"', '15"', '17"']
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
];
|
|
221
|
+
|
|
222
|
+
console.log('Разные стратегии обработки массивов:');
|
|
223
|
+
|
|
224
|
+
// Стратегия 1: Объединение через запятую (по умолчанию)
|
|
225
|
+
const strategy1 = preprocessDataWithFlattening(arrayData, {
|
|
226
|
+
flatten: true,
|
|
227
|
+
arrayHandling: 'join'
|
|
228
|
+
});
|
|
229
|
+
console.log('\n1. Объединение через запятую:');
|
|
230
|
+
console.log(JSON.stringify(strategy1, null, 2));
|
|
231
|
+
|
|
232
|
+
// Стратегия 2: Сериализация JSON
|
|
233
|
+
const strategy2 = preprocessDataWithFlattening(arrayData, {
|
|
234
|
+
flatten: true,
|
|
235
|
+
arrayHandling: 'stringify'
|
|
236
|
+
});
|
|
237
|
+
console.log('\n2. Сериализация JSON:');
|
|
238
|
+
console.log(JSON.stringify(strategy2, null, 2));
|
|
239
|
+
|
|
240
|
+
// Пример 5: Интеграция с существующим API
|
|
241
|
+
console.log('\n\n=== Пример 5: Интеграция с существующим API ===\n');
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Расширенная версия jsonToCsv с поддержкой flattening
|
|
245
|
+
*/
|
|
246
|
+
function jsonToCsvWithFlattening(data, options = {}) {
|
|
247
|
+
const {
|
|
248
|
+
flatten = false,
|
|
249
|
+
flattenSeparator = '.',
|
|
250
|
+
flattenMaxDepth = 3,
|
|
251
|
+
arrayHandling = 'stringify',
|
|
252
|
+
...csvOptions
|
|
253
|
+
} = options;
|
|
254
|
+
|
|
255
|
+
// Предобработка с flattening
|
|
256
|
+
const processedData = preprocessDataWithFlattening(data, {
|
|
257
|
+
flatten,
|
|
258
|
+
separator: flattenSeparator,
|
|
259
|
+
maxDepth: flattenMaxDepth,
|
|
260
|
+
arrayHandling
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// Используем существующую функцию jsonToCsv
|
|
264
|
+
return jsonToCsv(processedData, csvOptions);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Демонстрация
|
|
268
|
+
const complexData = [
|
|
269
|
+
{
|
|
270
|
+
id: 'USER-001',
|
|
271
|
+
personal: {
|
|
272
|
+
name: 'Charlie Brown',
|
|
273
|
+
birth: {
|
|
274
|
+
date: '1990-05-15',
|
|
275
|
+
place: 'Springfield'
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
employment: {
|
|
279
|
+
company: 'Tech Corp',
|
|
280
|
+
position: 'Senior Developer',
|
|
281
|
+
skills: ['JavaScript', 'TypeScript', 'Node.js', 'React']
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
];
|
|
285
|
+
|
|
286
|
+
console.log('Без flattening:');
|
|
287
|
+
const csvWithout = jsonToCsvWithFlattening(complexData, { flatten: false });
|
|
288
|
+
console.log(csvWithout);
|
|
289
|
+
|
|
290
|
+
console.log('\nС flattening:');
|
|
291
|
+
const csvWith = jsonToCsvWithFlattening(complexData, {
|
|
292
|
+
flatten: true,
|
|
293
|
+
flattenSeparator: '_',
|
|
294
|
+
flattenMaxDepth: 4
|
|
295
|
+
});
|
|
296
|
+
console.log(csvWith);
|
|
297
|
+
|
|
298
|
+
console.log('\n\n=== Рекомендации по улучшению jtcsv ===\n');
|
|
299
|
+
console.log('1. Добавить опцию "flatten" в jsonToCsv для автоматического разворачивания вложенных объектов');
|
|
300
|
+
console.log('2. Добавить параметры для контроля flattening:');
|
|
301
|
+
console.log(' - flattenSeparator: разделитель для вложенных ключей (по умолчанию ".")');
|
|
302
|
+
console.log(' - flattenMaxDepth: максимальная глубина разворачивания');
|
|
303
|
+
console.log(' - arrayHandling: стратегия обработки массивов');
|
|
304
|
+
console.log('3. Добавить функцию flattenObject в публичное API');
|
|
305
|
+
console.log('4. Обновить документацию с примерами обработки сложных JSON структур');
|
|
306
|
+
console.log('5. Добавить тесты для edge cases вложенных объектов');
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Пример обработки вложенных объектов в jtcsv
|
|
3
|
+
* Демонстрирует улучшенную поддержку сложных JSON структур
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { jsonToCsv, preprocessData, deepUnwrap } = await import("../../index");
|
|
7
|
+
|
|
8
|
+
// Пример 1: Простые вложенные объекты
|
|
9
|
+
const simpleNestedData = [
|
|
10
|
+
{
|
|
11
|
+
id: 1,
|
|
12
|
+
name: 'John Doe',
|
|
13
|
+
profile: {
|
|
14
|
+
age: 30,
|
|
15
|
+
email: 'john@example.com',
|
|
16
|
+
address: {
|
|
17
|
+
city: 'New York',
|
|
18
|
+
country: 'USA'
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
tags: ['developer', 'javascript', 'nodejs']
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 2,
|
|
25
|
+
name: 'Jane Smith',
|
|
26
|
+
profile: {
|
|
27
|
+
age: 25,
|
|
28
|
+
email: 'jane@example.com',
|
|
29
|
+
address: {
|
|
30
|
+
city: 'London',
|
|
31
|
+
country: 'UK'
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
tags: ['designer', 'ui', 'ux']
|
|
35
|
+
}
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
console.log('=== Пример 1: Простые вложенные объекты ===\n');
|
|
39
|
+
|
|
40
|
+
// Текущая реализация (deepUnwrap)
|
|
41
|
+
console.log('Текущая реализация (deepUnwrap):');
|
|
42
|
+
const processed1 = preprocessData(simpleNestedData);
|
|
43
|
+
console.log('Обработанные данные:', JSON.stringify(processed1, null, 2));
|
|
44
|
+
|
|
45
|
+
const csv1 = jsonToCsv(processed1);
|
|
46
|
+
console.log('\nCSV результат:');
|
|
47
|
+
console.log(csv1);
|
|
48
|
+
|
|
49
|
+
// Пример 2: Сложные вложенные структуры
|
|
50
|
+
const complexNestedData = [
|
|
51
|
+
{
|
|
52
|
+
orderId: 'ORD-001',
|
|
53
|
+
customer: {
|
|
54
|
+
id: 'CUST-001',
|
|
55
|
+
name: 'Acme Corp',
|
|
56
|
+
contact: {
|
|
57
|
+
primary: {
|
|
58
|
+
name: 'Alice Johnson',
|
|
59
|
+
phone: '+1-555-1234',
|
|
60
|
+
email: 'alice@acme.com'
|
|
61
|
+
},
|
|
62
|
+
secondary: {
|
|
63
|
+
name: 'Bob Smith',
|
|
64
|
+
phone: '+1-555-5678',
|
|
65
|
+
email: 'bob@acme.com'
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
items: [
|
|
70
|
+
{
|
|
71
|
+
productId: 'PROD-001',
|
|
72
|
+
name: 'Laptop',
|
|
73
|
+
quantity: 2,
|
|
74
|
+
price: 999.99,
|
|
75
|
+
specifications: {
|
|
76
|
+
cpu: 'Intel i7',
|
|
77
|
+
ram: '16GB',
|
|
78
|
+
storage: '512GB SSD'
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
productId: 'PROD-002',
|
|
83
|
+
name: 'Mouse',
|
|
84
|
+
quantity: 1,
|
|
85
|
+
price: 49.99
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
metadata: {
|
|
89
|
+
createdAt: '2024-01-15T10:30:00Z',
|
|
90
|
+
updatedAt: '2024-01-16T14:45:00Z',
|
|
91
|
+
status: 'completed',
|
|
92
|
+
notes: ['Urgent delivery', 'Gift wrapping requested']
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
console.log('\n\n=== Пример 2: Сложные вложенные структуры ===\n');
|
|
98
|
+
|
|
99
|
+
console.log('Текущая реализация (ограничения):');
|
|
100
|
+
const processed2 = preprocessData(complexNestedData);
|
|
101
|
+
console.log('Обработанные данные (первые 500 символов):');
|
|
102
|
+
console.log(JSON.stringify(processed2, null, 2).substring(0, 500) + '...');
|
|
103
|
+
|
|
104
|
+
// Пример 3: Предлагаемые улучшения
|
|
105
|
+
console.log('\n\n=== Пример 3: Предлагаемые улучшения ===\n');
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Улучшенная функция flattenObject для автоматического разворачивания вложенных структур
|
|
109
|
+
*/
|
|
110
|
+
function flattenObject(obj, prefix = '', separator = '.', maxDepth = 3, currentDepth = 0) {
|
|
111
|
+
if (currentDepth >= maxDepth) {
|
|
112
|
+
return { [prefix || 'value']: JSON.stringify(obj) };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const result = {};
|
|
116
|
+
|
|
117
|
+
for (const key in obj) {
|
|
118
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
119
|
+
const value = obj[key];
|
|
120
|
+
const newKey = prefix ? `${prefix}${separator}${key}` : key;
|
|
121
|
+
|
|
122
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
123
|
+
// Рекурсивно разворачиваем объекты
|
|
124
|
+
const flattened = flattenObject(
|
|
125
|
+
value,
|
|
126
|
+
newKey,
|
|
127
|
+
separator,
|
|
128
|
+
maxDepth,
|
|
129
|
+
currentDepth + 1
|
|
130
|
+
);
|
|
131
|
+
Object.assign(result, flattened);
|
|
132
|
+
} else if (Array.isArray(value)) {
|
|
133
|
+
// Обработка массивов
|
|
134
|
+
if (value.length === 0) {
|
|
135
|
+
result[newKey] = '';
|
|
136
|
+
} else if (value.every(item => typeof item === 'string' || typeof item === 'number')) {
|
|
137
|
+
// Простые массивы - объединяем через запятую
|
|
138
|
+
result[newKey] = value.join(', ');
|
|
139
|
+
} else {
|
|
140
|
+
// Сложные массивы - сериализуем
|
|
141
|
+
result[newKey] = JSON.stringify(value);
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
// Примитивные значения
|
|
145
|
+
result[newKey] = value;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Улучшенная функция preprocessData с поддержкой flattening
|
|
155
|
+
*/
|
|
156
|
+
function preprocessDataWithFlattening(data, options = {}) {
|
|
157
|
+
const {
|
|
158
|
+
flatten = false,
|
|
159
|
+
separator = '.',
|
|
160
|
+
maxDepth = 3,
|
|
161
|
+
arrayHandling = 'stringify' // 'stringify', 'join', 'expand'
|
|
162
|
+
} = options;
|
|
163
|
+
|
|
164
|
+
if (!Array.isArray(data)) {
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return data.map(item => {
|
|
169
|
+
if (!item || typeof item !== 'object') {
|
|
170
|
+
return {};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (flatten) {
|
|
174
|
+
return flattenObject(item, '', separator, maxDepth);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Стандартная обработка (совместимость)
|
|
178
|
+
const processed = {};
|
|
179
|
+
for (const key in item) {
|
|
180
|
+
if (Object.prototype.hasOwnProperty.call(item, key)) {
|
|
181
|
+
const value = item[key];
|
|
182
|
+
if (value && typeof value === 'object') {
|
|
183
|
+
processed[key] = deepUnwrap(value);
|
|
184
|
+
} else {
|
|
185
|
+
processed[key] = value;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return processed;
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Демонстрация улучшенной обработки
|
|
194
|
+
console.log('Улучшенная обработка с flattening:');
|
|
195
|
+
const flattened = preprocessDataWithFlattening(simpleNestedData, { flatten: true });
|
|
196
|
+
console.log('Развернутые данные:');
|
|
197
|
+
console.log(JSON.stringify(flattened, null, 2));
|
|
198
|
+
|
|
199
|
+
const csvFlattened = jsonToCsv(flattened);
|
|
200
|
+
console.log('\nCSV с развернутыми полями:');
|
|
201
|
+
console.log(csvFlattened);
|
|
202
|
+
|
|
203
|
+
// Пример 4: Разные стратегии обработки массивов
|
|
204
|
+
console.log('\n\n=== Пример 4: Обработка массивов ===\n');
|
|
205
|
+
|
|
206
|
+
const arrayData = [
|
|
207
|
+
{
|
|
208
|
+
id: 1,
|
|
209
|
+
name: 'Product A',
|
|
210
|
+
categories: ['Electronics', 'Computers', 'Laptops'],
|
|
211
|
+
reviews: [
|
|
212
|
+
{ user: 'Alice', rating: 5, comment: 'Great product!' },
|
|
213
|
+
{ user: 'Bob', rating: 4, comment: 'Good value' }
|
|
214
|
+
],
|
|
215
|
+
attributes: {
|
|
216
|
+
colors: ['Black', 'Silver', 'Space Gray'],
|
|
217
|
+
sizes: ['13"', '15"', '17"']
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
];
|
|
221
|
+
|
|
222
|
+
console.log('Разные стратегии обработки массивов:');
|
|
223
|
+
|
|
224
|
+
// Стратегия 1: Объединение через запятую (по умолчанию)
|
|
225
|
+
const strategy1 = preprocessDataWithFlattening(arrayData, {
|
|
226
|
+
flatten: true,
|
|
227
|
+
arrayHandling: 'join'
|
|
228
|
+
});
|
|
229
|
+
console.log('\n1. Объединение через запятую:');
|
|
230
|
+
console.log(JSON.stringify(strategy1, null, 2));
|
|
231
|
+
|
|
232
|
+
// Стратегия 2: Сериализация JSON
|
|
233
|
+
const strategy2 = preprocessDataWithFlattening(arrayData, {
|
|
234
|
+
flatten: true,
|
|
235
|
+
arrayHandling: 'stringify'
|
|
236
|
+
});
|
|
237
|
+
console.log('\n2. Сериализация JSON:');
|
|
238
|
+
console.log(JSON.stringify(strategy2, null, 2));
|
|
239
|
+
|
|
240
|
+
// Пример 5: Интеграция с существующим API
|
|
241
|
+
console.log('\n\n=== Пример 5: Интеграция с существующим API ===\n');
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Расширенная версия jsonToCsv с поддержкой flattening
|
|
245
|
+
*/
|
|
246
|
+
function jsonToCsvWithFlattening(data, options = {}) {
|
|
247
|
+
const {
|
|
248
|
+
flatten = false,
|
|
249
|
+
flattenSeparator = '.',
|
|
250
|
+
flattenMaxDepth = 3,
|
|
251
|
+
arrayHandling = 'stringify',
|
|
252
|
+
...csvOptions
|
|
253
|
+
} = options;
|
|
254
|
+
|
|
255
|
+
// Предобработка с flattening
|
|
256
|
+
const processedData = preprocessDataWithFlattening(data, {
|
|
257
|
+
flatten,
|
|
258
|
+
separator: flattenSeparator,
|
|
259
|
+
maxDepth: flattenMaxDepth,
|
|
260
|
+
arrayHandling
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// Используем существующую функцию jsonToCsv
|
|
264
|
+
return jsonToCsv(processedData, csvOptions);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Демонстрация
|
|
268
|
+
const complexData = [
|
|
269
|
+
{
|
|
270
|
+
id: 'USER-001',
|
|
271
|
+
personal: {
|
|
272
|
+
name: 'Charlie Brown',
|
|
273
|
+
birth: {
|
|
274
|
+
date: '1990-05-15',
|
|
275
|
+
place: 'Springfield'
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
employment: {
|
|
279
|
+
company: 'Tech Corp',
|
|
280
|
+
position: 'Senior Developer',
|
|
281
|
+
skills: ['JavaScript', 'TypeScript', 'Node.js', 'React']
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
];
|
|
285
|
+
|
|
286
|
+
console.log('Без flattening:');
|
|
287
|
+
const csvWithout = jsonToCsvWithFlattening(complexData, { flatten: false });
|
|
288
|
+
console.log(csvWithout);
|
|
289
|
+
|
|
290
|
+
console.log('\nС flattening:');
|
|
291
|
+
const csvWith = jsonToCsvWithFlattening(complexData, {
|
|
292
|
+
flatten: true,
|
|
293
|
+
flattenSeparator: '_',
|
|
294
|
+
flattenMaxDepth: 4
|
|
295
|
+
});
|
|
296
|
+
console.log(csvWith);
|
|
297
|
+
|
|
298
|
+
console.log('\n\n=== Рекомендации по улучшению jtcsv ===\n');
|
|
299
|
+
console.log('1. Добавить опцию "flatten" в jsonToCsv для автоматического разворачивания вложенных объектов');
|
|
300
|
+
console.log('2. Добавить параметры для контроля flattening:');
|
|
301
|
+
console.log(' - flattenSeparator: разделитель для вложенных ключей (по умолчанию ".")');
|
|
302
|
+
console.log(' - flattenMaxDepth: максимальная глубина разворачивания');
|
|
303
|
+
console.log(' - arrayHandling: стратегия обработки массивов');
|
|
304
|
+
console.log('3. Добавить функцию flattenObject в публичное API');
|
|
305
|
+
console.log('4. Обновить документацию с примерами обработки сложных JSON структур');
|
|
306
|
+
console.log('5. Добавить тесты для edge cases вложенных объектов');
|