UNPKG

json-data-to-csv

Version:

A TypeScript library to convert array of objects to CSV format with customizable delimiter

721 lines (565 loc) โ€ข 19.8 kB
<div align="center"> <h1>๐Ÿš€ json-data-to-csv</h1> <p><strong>A powerful, lightweight TypeScript library for converting JSON arrays to CSV format</strong></p> [![npm version](https://img.shields.io/npm/v/json-data-to-csv.svg)](https://www.npmjs.com/package/json-data-to-csv) [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/) [![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit/) [![Zero Dependencies](https://img.shields.io/badge/dependencies-0-brightgreen.svg)](https://www.npmjs.com/package/json-data-to-csv) <p>Transform your JSON data into properly formatted CSV with ease! ๐Ÿ“Š</p> </div> --- ## โœจ Features - ๐Ÿ”„ **JSON to CSV Conversion** - Seamlessly convert arrays of objects to CSV format - โš™๏ธ **Customizable Delimiter** - Use comma, semicolon, or any custom delimiter - ๐ŸŽฏ **Smart Header Generation** - Automatically detects and creates headers from object keys - ๐Ÿ›ก๏ธ **CSV Escaping** - Properly handles special characters, quotes, and newlines - โšก **TypeScript First** - Full type safety with comprehensive type definitions - ๐Ÿ” **Error Handling** - Detailed error messages with specific error codes - ๐Ÿ“ฆ **Zero Dependencies** - Lightweight with no external dependencies - ๐ŸŽจ **Data Type Support** - Handles strings, numbers, booleans, objects, null, undefined ## ๐Ÿ“ฆ Installation ```bash # Using npm npm install json-data-to-csv # Using yarn yarn add json-data-to-csv # Using pnpm pnpm add json-data-to-csv ``` ## ๐Ÿš€ Quick Start ```typescript import { parse } from 'json-data-to-csv'; // Simple conversion const data = [ { name: 'Alice', age: 30, role: 'Developer' }, { name: 'Bob', age: 25, role: 'Designer' }, ]; const csv = parse(data); console.log(csv); // Output: // name,age,role // Alice,30,Developer // Bob,25,Designer ``` ## ๐Ÿ“– Usage Examples ### ๐ŸŽฏ Basic Usage Convert a simple array of objects to CSV format: ```typescript import { parse } from 'json-data-to-csv'; const employees = [ { name: 'John Doe', age: 30, city: 'New York', salary: 75000 }, { name: 'Jane Smith', age: 25, city: 'Los Angeles', salary: 80000 }, { name: 'Mike Johnson', age: 35, city: 'Chicago', salary: 90000 }, ]; const csv = parse(employees); console.log(csv); ``` **Output:** ```csv name,age,city,salary John Doe,30,New York,75000 Jane Smith,25,Los Angeles,80000 Mike Johnson,35,Chicago,90000 ``` ### ๐Ÿ”ง Custom Delimiter Use different delimiters for various regional formats: ```typescript import { parse } from 'json-data-to-csv'; const data = [ { product: 'Laptop', price: 999.99, stock: 50 }, { product: 'Mouse', price: 29.99, stock: 100 }, ]; // European format with semicolon const csvSemicolon = parse(data, { delimiter: ';' }); console.log(csvSemicolon); // Tab-separated values const tsvFormat = parse(data, { delimiter: '\t' }); console.log(tsvFormat); // Pipe-separated values const psvFormat = parse(data, { delimiter: '|' }); console.log(psvFormat); ``` **Output (semicolon):** ```csv product;price;stock Laptop;999.99;50 Mouse;29.99;100 ``` ### ๐ŸŽจ Mixed Data Types Handle various data types seamlessly: ```typescript import { parse } from 'json-data-to-csv'; const mixedData = [ { id: 1, name: 'John Doe', active: true, score: 95.5, metadata: { role: 'admin', permissions: ['read', 'write'] }, lastLogin: new Date('2025-01-15'), description: null, notes: undefined, tags: ['developer', 'senior'], }, { id: 2, name: 'Jane Smith', active: false, score: 87.2, metadata: { role: 'user' }, lastLogin: new Date('2025-01-10'), bio: 'Software engineer with 5 years of experience', }, ]; const csv = parse(mixedData); console.log(csv); ``` **Output:** ```csv id,name,active,score,metadata,lastLogin,description,notes,tags,bio 1,John Doe,true,95.5,"{""role"":""admin"",""permissions"":[""read"",""write""]}",2025-01-15T00:00:00.000Z,,,"[""developer"",""senior""]", 2,Jane Smith,false,87.2,"{""role"":""user""}",2025-01-10T00:00:00.000Z,,,,"Software engineer with 5 years of experience" ``` ### ๐Ÿ”€ Dynamic Properties Handle objects with different property sets: ```typescript import { parse } from 'json-data-to-csv'; const dynamicData = [ { name: 'Alice', age: 30, department: 'Engineering' }, { name: 'Bob', city: 'Seattle', country: 'USA', zipCode: '98101' }, { age: 40, email: 'charlie@example.com', phone: '+1-555-0123' }, { name: 'Diana', department: 'Marketing', email: 'diana@example.com', manager: 'Alice', }, ]; const csv = parse(dynamicData); console.log(csv); ``` **Output:** ```csv name,age,department,city,country,zipCode,email,phone,manager Alice,30,Engineering,,,,,, Bob,,,"Seattle",USA,98101,,, ,40,,,,,charlie@example.com,+1-555-0123, Diana,,Marketing,,,,"diana@example.com",,Alice ``` ### ๐Ÿ›ก๏ธ Special Character Handling Properly escape CSV special characters: ```typescript import { parse } from 'json-data-to-csv'; const specialData = [ { name: 'John "Johnny" Doe', bio: 'Software engineer,\nspecializing in web development', quote: 'He said, "Hello, world!"', note: 'Contains\r\nWindows line endings', }, { name: "Jane O'Connor", bio: 'Data scientist; loves statistics', quote: 'Data tells a story', note: 'Simple description', }, ]; const csv = parse(specialData); console.log(csv); ``` **Output:** ```csv name,bio,quote,note "John ""Johnny"" Doe","Software engineer, specializing in web development","He said, ""Hello, world!""","Contains Windows line endings" Jane O'Connor,"Data scientist; loves statistics",Data tells a story,Simple description ``` ## ๐Ÿ“š API Reference ### `parse(data, options?)` Converts an array of objects to CSV format with intelligent header detection. ```typescript function parse(data: JsonData, options?: ParseOptions): string; ``` #### Parameters | Parameter | Type | Required | Description | | --------- | -------------- | -------- | ---------------------------------- | | `data` | `JsonData` | โœ… | Array of objects to convert to CSV | | `options` | `ParseOptions` | โŒ | Configuration options for parsing | #### ParseOptions | Property | Type | Default | Description | | ----------- | -------- | ------- | ------------------------------------- | | `delimiter` | `string` | `','` | Character used to separate CSV fields | #### Returns | Type | Description | | -------- | -------------------------------------------------- | | `string` | CSV formatted string with header row and data rows | #### Throws | Exception | Description | | ---------------- | ------------------------------------------------------ | | `JsonToCsvError` | When input validation fails or processing errors occur | ### ๐ŸŽฏ Type Definitions ```typescript // Main data type - array of objects type JsonData = Record<string, any>[]; // Configuration options interface ParseOptions { delimiter?: string; } // Custom error class with error codes class JsonToCsvError extends Error { constructor(message: string, public code?: string); name: 'JsonToCsvError'; code?: string; } ``` ### ๐ŸŽ›๏ธ Supported Data Types | JavaScript Type | CSV Output | Example | | --------------- | --------------------- | ------------------------------- | | `string` | Direct value | `"Hello"` โ†’ `Hello` | | `number` | String representation | `42` โ†’ `42` | | `boolean` | String representation | `true` โ†’ `true` | | `null` | Empty field | `null` โ†’ `` | | `undefined` | Empty field | `undefined` โ†’ `` | | `object` | JSON string | `{a:1}` โ†’ `"{""a"":1}"` | | `array` | JSON string | `[1,2]` โ†’ `"[1,2]"` | | `Date` | ISO string | `new Date()` โ†’ `2025-01-15T...` | ## ๐Ÿšจ Error Handling The library provides comprehensive error handling with specific error codes for easy debugging: ```typescript import { parse, JsonToCsvError } from 'json-data-to-csv'; try { const csv = parse([]); } catch (error) { if (error instanceof JsonToCsvError) { console.error(`โŒ Error: ${error.message}`); console.error(`๐Ÿ” Code: ${error.code}`); // Handle specific error types switch (error.code) { case 'EMPTY_INPUT': console.log('๐Ÿ’ก Tip: Provide a non-empty array of objects'); break; case 'INVALID_DELIMITER': console.log('๐Ÿ’ก Tip: Use a non-empty string as delimiter'); break; default: console.log('๐Ÿ’ก Check the documentation for more details'); } } } ``` ### ๐Ÿ“‹ Error Codes Reference | Error Code | Description | Example Cause | | ---------------------- | ----------------------------- | -------------------------------- | | `INVALID_INPUT` | Input is not an array | `parse("string")` | | `EMPTY_INPUT` | Array is empty | `parse([])` | | `INVALID_DELIMITER` | Invalid delimiter | `parse(data, { delimiter: "" })` | | `INVALID_DATA_TYPE` | Non-object in array | `parse([null, "string"])` | | `NO_PROPERTIES` | Objects have no properties | `parse([{}, {}])` | | `SERIALIZATION_ERROR` | Failed to serialize object | Circular reference in object | | `ROW_PROCESSING_ERROR` | Error processing specific row | Malformed data in row | | `UNEXPECTED_ERROR` | Unexpected internal error | System/memory issues | ### ๐Ÿ› ๏ธ Error Handling Examples ```typescript import { parse, JsonToCsvError } from 'json-data-to-csv'; // Example 1: Empty array try { parse([]); } catch (error) { console.log(error.message); // "Input data cannot be empty" console.log(error.code); // "EMPTY_INPUT" } // Example 2: Invalid data type try { parse(['string', 123, null] as any); } catch (error) { console.log(error.message); // "All data items must be objects" console.log(error.code); // "INVALID_DATA_TYPE" } // Example 3: Invalid delimiter try { parse([{ name: 'John' }], { delimiter: null as any }); } catch (error) { console.log(error.message); // "Delimiter must be a non-empty string" console.log(error.code); // "INVALID_DELIMITER" } ``` ## ๐Ÿ” CSV Escaping & Special Characters The library follows RFC 4180 standards and properly handles all CSV special characters: ### ๐ŸŽฏ Automatic Escaping Rules | Scenario | Handling | Example | | ---------------------- | ------------------ | --------------------- | | **Delimiter in field** | Wrap in quotes | `"Contains, comma"` | | **Double quotes** | Double the quotes | `"He said ""Hello"""` | | **Newlines** | Preserve in quotes | `"Line 1\nLine 2"` | | **Carriage returns** | Preserve in quotes | `"Windows\r\nending"` | ### ๐Ÿงช Real-world Examples ```typescript import { parse } from 'json-data-to-csv'; // Example with various special characters const problematicData = [ { name: 'John "The Coder" Smith', address: '123 Main St,\nApt 4B\nNew York, NY', bio: 'Software engineer, loves "clean code" principles', note: 'Contact via email; phone available Mon-Fri', tags: 'javascript,typescript,react', }, ]; const csv = parse(problematicData); console.log(csv); ``` **Output:** ```csv name,address,bio,note,tags "John ""The Coder"" Smith","123 Main St, Apt 4B New York, NY","Software engineer, loves ""clean code"" principles","Contact via email; phone available Mon-Fri","javascript,typescript,react" ``` ### ๐ŸŒ International Support ```typescript // Works with international characters and various delimiters const internationalData = [ { name: 'Josรฉ Marรญa', city: 'Sรฃo Paulo', note: 'Espaรฑol, Portuguรชs' }, { name: '็”ฐไธญๅคช้ƒŽ', city: 'ๆฑไบฌ', note: 'ๆ—ฅๆœฌ่ชžใ‚ตใƒใƒผใƒˆ' }, { name: 'Franรงois', city: 'Paris', note: 'Caractรจres accentuรฉs' }, ]; // European format (semicolon delimiter) const europeanCsv = parse(internationalData, { delimiter: ';' }); console.log(europeanCsv); ``` ## ๐Ÿ—๏ธ Real-world Use Cases ### ๐Ÿ“Š Data Export Dashboard ```typescript import { parse } from 'json-data-to-csv'; // Export user analytics data const analyticsData = [ { userId: 'user_001', name: 'Alice Johnson', email: 'alice@company.com', lastLogin: '2025-06-04T10:30:00Z', pageViews: 245, sessionDuration: 1800, // seconds conversions: 3, revenue: 299.97, }, // ... more user data ]; const csv = parse(analyticsData); // Save to file or send as download console.log('๐Ÿ“ˆ Analytics Export Ready!'); ``` ### ๐Ÿ›’ E-commerce Product Catalog ```typescript // Export product inventory const products = [ { sku: 'LAPTOP-001', name: 'MacBook Pro 14"', category: 'Electronics', price: 1999.99, stock: 50, description: 'High-performance laptop for professionals', specs: { ram: '16GB', storage: '512GB SSD', chip: 'M3 Pro' }, tags: ['laptop', 'apple', 'professional'], inStock: true, }, ]; const productCsv = parse(products, { delimiter: '|' }); ``` ### ๐Ÿ“‹ HR Employee Reports ```typescript // Export employee data for payroll const employees = [ { employeeId: 'EMP001', fullName: 'John Smith', department: 'Engineering', position: 'Senior Developer', hireDate: '2023-01-15', salary: 95000, benefits: { health: true, dental: true, vision: false }, skills: ['JavaScript', 'Python', 'React'], manager: 'Jane Doe', }, ]; const hrCsv = parse(employees); ``` ### ๐Ÿฆ Financial Transaction Reports ```typescript // Export financial transactions const transactions = [ { transactionId: 'TXN_20250604_001', date: '2025-06-04', amount: -89.5, description: 'Online Purchase - Amazon', category: 'Shopping', account: 'Checking ***1234', merchant: { name: 'Amazon.com', location: 'Online' }, status: 'Completed', }, ]; const financialCsv = parse(transactions, { delimiter: ';' }); ``` ## ๐Ÿš€ Performance & Best Practices ### โšก Performance Tips - **Large datasets**: The library handles thousands of records efficiently - **Memory usage**: Streaming not required for typical web application datasets - **Complex objects**: Nested objects are serialized as JSON strings automatically ```typescript // โœ… Good: Efficient for typical use cases const largeDataset = Array.from({ length: 10000 }, (_, i) => ({ id: i, name: `User ${i}`, email: `user${i}@example.com`, active: i % 2 === 0, })); const csv = parse(largeDataset); // Handles efficiently ``` ### ๐ŸŽฏ Best Practices ```typescript // โœ… Use consistent property names across objects const goodData = [ { id: 1, name: 'John', email: 'john@example.com' }, { id: 2, name: 'Jane', email: 'jane@example.com' }, ]; // โš ๏ธ Inconsistent properties create sparse CSV const sparseData = [ { id: 1, name: 'John' }, { email: 'jane@example.com', phone: '555-0123' }, ]; // โœ… Handle errors appropriately try { const csv = parse(userData); return csv; } catch (error) { if (error instanceof JsonToCsvError) { logger.error(`CSV conversion failed: ${error.message}`, { code: error.code, }); return null; } throw error; } ``` ## ๐Ÿ› ๏ธ Development ### ๐Ÿ—๏ธ Building the Project ```bash # Install dependencies npm install # Build TypeScript to JavaScript npm run build # Build in watch mode for development npm run dev ``` ### ๐Ÿงช Testing ```bash # Run all tests npm test # Run tests in watch mode npm run test:watch # Run tests with coverage npm test -- --coverage ``` ### ๐Ÿ” Project Structure ``` json-data-to-csv/ โ”œโ”€โ”€ ๐Ÿ“ src/ โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ index.ts # Main library code โ”‚ โ””โ”€โ”€ ๐Ÿ“ __tests__/ โ”‚ โ””โ”€โ”€ ๐Ÿ“„ index.test.ts # Comprehensive test suite โ”œโ”€โ”€ ๐Ÿ“ dist/ # Compiled output โ”‚ โ”œโ”€โ”€ ๐Ÿ“„ index.js # ES modules output โ”‚ โ””โ”€โ”€ ๐Ÿ“„ index.d.ts # TypeScript definitions โ”œโ”€โ”€ ๐Ÿ“„ package.json # Package configuration โ”œโ”€โ”€ ๐Ÿ“„ tsconfig.json # TypeScript configuration โ”œโ”€โ”€ ๐Ÿ“„ jest.config.js # Test configuration โ””โ”€โ”€ ๐Ÿ“„ README.md # Documentation ``` ### ๐Ÿ”ง Local Development ```bash # Clone and setup git clone <repository-url> cd jsontocsv npm install # Run tests while developing npm run test:watch # Test your changes node test.js ``` ## ๐Ÿ“„ License This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) file for details. ``` MIT License - feel free to use this library in your projects! ๐ŸŽ‰ ``` ## ๐Ÿค Contributing We welcome contributions! Here's how you can help improve this library: ### ๐Ÿ› Reporting Bugs 1. **Check existing issues** first to avoid duplicates 2. **Create a detailed issue** with: - Clear description of the problem - Steps to reproduce - Expected vs actual behavior - Sample data that causes the issue ### ๐Ÿš€ Submitting Changes 1. **Fork** the repository 2. **Create** your feature branch: ```bash git checkout -b feature/amazing-feature ``` 3. **Make** your changes with tests 4. **Test** thoroughly: ```bash npm test npm run build ``` 5. **Commit** your changes: ```bash git commit -m 'Add some amazing feature' ``` 6. **Push** to the branch: ```bash git push origin feature/amazing-feature ``` 7. **Open** a Pull Request with: - Clear description of changes - Link to any related issues - Screenshots/examples if applicable ### ๐ŸŽฏ Development Guidelines - **Write tests** for new features - **Follow TypeScript** best practices - **Update documentation** for API changes - **Maintain backward compatibility** when possible - **Keep dependencies minimal** (currently zero dependencies!) ## ๐Ÿ—บ๏ธ Roadmap ### ๐Ÿ”ฎ Future Features - [ ] **Streaming support** for very large datasets - [ ] **Custom formatters** for specific data types - [ ] **Schema validation** options - [ ] **Performance benchmarks** and optimizations - [ ] **Browser compatibility** testing - [ ] **Additional output formats** (TSV, PSV, etc.) ### ๐Ÿ“ˆ Version History | Version | Date | Changes | | --------- | ---------- | ------------------------------------------ | | **1.0.0** | 2025-06-04 | ๐ŸŽ‰ Initial release with core functionality | | | | โœ… JSON to CSV conversion | | | | โœ… Customizable delimiters | | | | โœ… Comprehensive error handling | | | | โœ… Full TypeScript support | | | | โœ… Zero dependencies | --- <div align="center"> <p><strong>Made with โค๏ธ by Ashish Patel</strong></p> <p> <a href="https://www.npmjs.com/package/json-data-to-csv">๐Ÿ“ฆ npm</a> โ€ข <a href="https://github.com/ashishpatel546/json-data-to-csv">๐Ÿ™ GitHub</a> โ€ข <a href="https://github.com/ashishpatel546/json-data-to-csv/issues">๐Ÿ› Issues</a> โ€ข <a href="https://github.com/ashishpatel546/json-data-to-csv/blob/main/CHANGELOG.md">๐Ÿ“‹ Changelog</a> </p> <p> <em>โญ Star this repo if you find it helpful!</em> </p> </div>