Comparing version 0.0.1 to 1.0.0
{ | ||
"name": "csv42", | ||
"description": "Small and fast CSV parser to convert JSON to CSV and CSV to JSON", | ||
"version": "1.0.0", | ||
"description": "Small and fast CSV parser to convert nested JSON to CSV and CSV to JSON", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/josdejong/csv42.git" | ||
}, | ||
"keywords": [ | ||
@@ -8,5 +13,77 @@ "csv", | ||
"csv2json", | ||
"json2csv" | ||
"json2csv", | ||
"fast", | ||
"simple", | ||
"nested", | ||
"flatten", | ||
"format", | ||
"parse", | ||
"delimiter", | ||
"header", | ||
"eol", | ||
"fields" | ||
], | ||
"version": "0.0.1" | ||
"type": "module", | ||
"main": "lib/cjs/index.js", | ||
"module": "lib/esm/index.js", | ||
"browser": "lib/umd/csv42.js", | ||
"types": "lib/types/index.d.ts", | ||
"exports": { | ||
".": { | ||
"import": "./lib/esm/index.js", | ||
"require": "./lib/cjs/index.js", | ||
"browser": "./lib/umd/csv42.js", | ||
"types": "./lib/types/index.d.ts" | ||
} | ||
}, | ||
"sideEffects": false, | ||
"scripts": { | ||
"test": "vitest src", | ||
"test-ci": "vitest run src", | ||
"coverage": "vitest run src --coverage", | ||
"lint": "prettier --check src benchmark README.md *.json", | ||
"format": "prettier --write src benchmark README.md *.json", | ||
"build": "npm-run-all build:**", | ||
"build:clean": "del-cli lib", | ||
"build:esm": "babel src --out-dir lib/esm --extensions \".ts\" --source-maps --config-file ./babel.config.json", | ||
"build:cjs": "babel src --out-dir lib/cjs --extensions \".ts\" --source-maps --config-file ./babel-cjs.config.json && cpy tools/cjs/package.json lib/cjs --flat", | ||
"build:umd": "rollup lib/esm/index.js --format umd --name csv42 --sourcemap --output.file lib/umd/csv42.js && cpy tools/cjs/package.json lib/umd --flat", | ||
"build:umd:min": "uglifyjs --compress --mangle --source-map --comments --output lib/umd/csv42.min.js -- lib/umd/csv42.js", | ||
"build:types": "tsc --project tsconfig-types.json", | ||
"build:validate": "vitest run test-lib", | ||
"build-and-test": "npm run test-ci && npm run lint && npm run build", | ||
"release": "npm-run-all release:**", | ||
"release:build-and-test": "npm run build-and-test", | ||
"release:version": "standard-version", | ||
"release:push": "git push && git push --tag", | ||
"release:publish": "npm publish", | ||
"release-dry-run": "npm run build-and-test && standard-version --dry-run", | ||
"prepare": "husky install" | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "7.21.0", | ||
"@babel/core": "7.21.0", | ||
"@babel/plugin-transform-typescript": "7.21.0", | ||
"@babel/preset-env": "7.20.2", | ||
"@babel/preset-typescript": "7.21.0", | ||
"@commitlint/cli": "17.4.4", | ||
"@commitlint/config-conventional": "17.4.4", | ||
"@vitest/coverage-c8": "0.28.5", | ||
"cpy-cli": "4.2.0", | ||
"csv-spectrum": "1.0.0", | ||
"del-cli": "5.0.0", | ||
"husky": "^8.0.3", | ||
"npm-run-all": "4.1.5", | ||
"prettier": "2.8.4", | ||
"standard-version": "9.5.0", | ||
"typescript": "4.9.5", | ||
"uglify-js": "3.17.4", | ||
"vite": "4.1.3", | ||
"vitest": "0.28.5" | ||
}, | ||
"files": [ | ||
"README.md", | ||
"LICENSE.md", | ||
"lib" | ||
] | ||
} |
211
README.md
@@ -1,3 +0,210 @@ | ||
# csv7 | ||
# csv42 | ||
coming soon... | ||
Convert **CSV to JSON** and **JSON to CSV** | ||
## Features | ||
- **2 way**: convert from and to CSV | ||
- **Simple**: straightforward and flexible API | ||
- **Lightweight**: <2KB gzipped with everything included, <1KB gzipped when only using `json2csv` | ||
- **Fast**: faster than the popular CSV libraries out there. See [benchmark](/benchmark). | ||
- **Modular**: only load what you use, thanks to ES5 modules and a plugin architecture | ||
- **Powerful**: | ||
- Configurable properties: `header`, `delimiter`, `eol` | ||
- Configurable `fields`, with custom value getters and setters and the ability to ignore fields | ||
- Configurable serialization and deserialization of values via `formatValue` and `parseValue` | ||
- Support for nested JSON objects: either flatten nested contents, or stringify as a JSON object | ||
- **Standards compliant**: adheres to the CSV standard [RFC 4180](https://datatracker.ietf.org/doc/html/rfc4180) | ||
- **Universal**: Created for the browser, but can be used in any JavaScript environment like node.js. | ||
Note that the parser has no streaming support. | ||
## Why? | ||
Well, you have to write a CSV parser at least once in you life, right? ;) | ||
The `csv42` library was developed specifically for https://jsoneditoronline.org. The library was developed for the browser. Besides being small and fast, one important feature is supporting nested JSON objects. So, why the name `csv42`? Just because [42](<https://simple.wikipedia.org/wiki/42_(answer)>) is a beautiful number and reminds us that there is a whole universe of beautiful CSV libraries out there. | ||
## Install | ||
``` | ||
npm install csv42 | ||
``` | ||
## Usage | ||
Install the library once: | ||
### Convert JSON to CSV | ||
```ts | ||
import { json2csv } from 'csv42' | ||
const users = [ | ||
{ id: 1, name: 'Joe', address: { city: 'New York', street: '1st Ave' } }, | ||
{ id: 2, name: 'Sarah', address: { city: 'Manhattan', street: 'Spring street' } } | ||
] | ||
// By default, nested JSON properties are flattened | ||
const csv = json2csv(users) | ||
console.log(csv) | ||
// id,name,address.city,address.street | ||
// 1,Joe,New York,1st Ave | ||
// 2,Sarah,Manhattan,Spring street | ||
// You can turn off flattening using the option `flatten` | ||
const csvFlat = json2csv(users, { flatten: false }) | ||
console.log(csvFlat) | ||
// id,name,address | ||
// 1,Joe,"{""city"":""New York"",""street"":""1st Ave""}" | ||
// 2,Sarah,"{""city"":""Manhattan"",""street"":""Spring street""}" | ||
// The CSV output can be fully customized and transformed using `fields`: | ||
const csvCustom = json2csv(users, { | ||
fields: [ | ||
{ name: 'name', getValue: (object) => object.name }, | ||
{ name: 'address', getValue: (object) => object.address.city + ' - ' + object.address.street } | ||
] | ||
}) | ||
console.log(csvCustom) | ||
// name,address | ||
// Joe,New York - 1st Ave | ||
// Sarah,Manhattan - Spring street | ||
``` | ||
### Convert CSV to JSON | ||
```ts | ||
import { csv2json } from 'csv42' | ||
const csv = `id,name,address.city,address.street | ||
1,Joe,New York,1st Ave | ||
2,Sarah,Manhattan,Spring street` | ||
// By default, fields containing a dot will be parsed inty nested JSON objects | ||
const users = csv2json(csv) | ||
console.log(users) | ||
// [ | ||
// { id: 1, name: 'Joe', address: { city: 'New York', street: '1st Ave' } }, | ||
// { id: 2, name: 'Sarah', address: { city: 'Manhattan', street: 'Spring street' } } | ||
// ] | ||
// Creating nested objects can be turned off using the option `nested` | ||
const usersFlat = csv2json(csv, { nested: false }) | ||
console.log(usersFlat) | ||
// [ | ||
// { id: 1, name: 'Joe', 'address.city': 'New York', 'address.street': '1st Ave' }, | ||
// { id: 2, name: 'Sarah', 'address.city': 'Manhattan', 'address.street': 'Spring street' } | ||
// ] | ||
// The JSON output can be customized using `fields` | ||
const usersCustom = csv2json(csv, { | ||
fields: [ | ||
{ name: 'name', setValue: (object, value) => (object.name = value) }, | ||
{ name: 'address.city', setValue: (object, value) => (object.city = value) } | ||
] | ||
}) | ||
console.log(usersCustom) | ||
// [ | ||
// { name: 'Joe', city: 'New York' }, | ||
// { name: 'Sarah', city: 'Manhattan' } | ||
// ] | ||
``` | ||
## API | ||
### `json2csv(json: NestedObject[], options?: CsvOptions) : string` | ||
Where `options` is an object with the following properties: | ||
| Option | Type | Description | | ||
| ------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| `header` | `boolean` | If true, a header will be created as first line of the CSV. | | ||
| `delimiter` | `string` | Default delimiter is `,`. A delimiter must be a single character. | | ||
| `eol` | `\r\n` or `\n` | End of line, can be `\r\n` (default) or `\n`. | | ||
| `flatten` | `boolean` or `(value: unknown) => boolean` | If `true` (default), nested objects and arrays will be flattened in multiple CSV columns. When `false`, nested objects and arrays will be serialized as JSON in a single CSV field. This behavior can be customized by providing your own callback function for `flatten`. For example, to flatten objects but not arrays, you can do `json2csv(json, { flatten: (value) => value ? value.constructor === Object : false })`. The option `flatten` is not applicable when `fields` is defined. | | ||
| `fields` | `CsvField[]` or `CsvFieldsParser` | A list with fields to be put into the CSV file. This allows specifying the order of the fields and which fields to include/excluded. | | ||
| `formatValue` | `ValueFormatter` | Function used to change any type of value into a serialized string for the CSV. The build in formatter will only enclose values in quotes when necessary, and will stringify nested JSON objects. | | ||
A simple example of a `ValueFormatter` is the following. This formatter will enclose every value in quotes: | ||
```ts | ||
function formatValue(value: unknown): string { | ||
return '"' + String(value) + '"' | ||
} | ||
``` | ||
### `csv2json(csv: string, options?: JsonOptions) : NestedObject[]` | ||
Where `options` is an object with the following properties: | ||
| Option | Type | Description | | ||
| ------------ | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| `header` | `boolean` | Should be set `true` when the first line of the CSV file contains a header | | ||
| `delimiter` | `string` | Default delimiter is `,`. A delimiter must be a single character. | | ||
| `nested` | `boolean` | If `true` (default), field names containing a dot will be parsed into nested JSON objects. The option `nested` is not applicable when `fields` is defined. | | ||
| `fields` | `JsonField[]` or `JsonFieldsParser` | A list with fields to be extracted from the CSV file into JSON. This allows specifying which fields are include/excluded, and how they will be put into the JSON object. A field can be specified either by name, like `{ name, setValue }`, or by the index of the columns in the CSV file, like `{ index, setValue }`. | | ||
| `parseValue` | `ValueParser` | Used to parse a stringified value into a value again (number, boolean, string, ...). The build in parser will parse numbers and booleans, and will parse stringified JSON objects. | | ||
A simple value parser can look as follows. This will keep all values as string: | ||
```ts | ||
function parseValue(value: string): unknown { | ||
return value.startsWith('"') ? value.substring(1, value.length - 1).replaceAll('""', '"') : value | ||
} | ||
``` | ||
### Utility functions | ||
The library exports a number of utility functions: | ||
| Function | Description | | ||
| ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| `createFormatValue(delimiter: string): (value: unknown) => string` | Create a function that can format (stringify) a value into a valid CSV value, escaping the value when needed. This function is used as default for the option `formatValue`. | | ||
| `parseValue(value: string): unknown` | Parse a string into a value, parse numbers into a number, etc. This is the function used by default for the option `parseValue`. | | ||
| `collectNestedPaths(records: NestedObject[], recurse: boolean): Path[]` | Loop over the data and collect all nested paths. This can be used to generate a list with fields. | | ||
| `parsePath(pathStr: string): Path` | Parse a path like `'items[3].name'` | | ||
| `function stringifyPath(path: Path): string` | Stringify a path into a string like `'items[3].name'` | | ||
| `getIn(object: NestedObject, path: Path): unknown` | Get a nested property from an object | | ||
| `setIn(object: NestedObject, path: Path, value: unknown): NestedObject` | Set a nested property in an object | | ||
## Alternatives | ||
- https://www.npmjs.com/package/csv | ||
- https://juanjodiaz.github.io/json2csv/ | ||
- https://www.npmjs.com/package/json-2-csv | ||
- https://www.npmjs.com/package/papaparse | ||
- https://www.npmjs.com/package/csvtojson | ||
- https://www.npmjs.com/package/csv-stringify | ||
- https://www.npmjs.com/package/csv-parser | ||
- https://www.npmjs.com/package/fast-csv | ||
- Any many many more... | ||
### Release | ||
To release a new version: | ||
``` | ||
$ npm run release | ||
``` | ||
This will: | ||
- lint | ||
- test | ||
- build | ||
- increment the version number | ||
- push the changes to git, add a git version tag | ||
- publish the npm package | ||
To try the build and see the change list without actually publishing: | ||
``` | ||
$ npm run release-dry-run | ||
``` | ||
## License | ||
`csv42` is released as open source under the permissive the [ISC license](LICENSE.md). | ||
**If you are using `csv42` commercially, there is a _social_ (but no legal) expectation that you help fund its maintenance. [Start here](https://github.com/sponsors/josdejong).** |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Empty package
Supply chain riskPackage does not contain any code. It may be removed, is name squatting, or the result of a faulty package publish.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
166199
63
0
1298
1
211
0
Yes
19