UNPKG

is-json-value

Version:
309 lines (221 loc) 8.35 kB
[![Node](https://img.shields.io/badge/-Node.js-808080?logo=node.js&colorA=404040&logoColor=66cc33)](https://www.npmjs.com/package/is-json-value) [![Browsers](https://img.shields.io/badge/-Browsers-808080?logo=firefox&colorA=404040)](https://unpkg.com/is-json-value?module) [![TypeScript](https://img.shields.io/badge/-Typed-808080?logo=typescript&colorA=404040&logoColor=0096ff)](/src/main.d.ts) [![Codecov](https://img.shields.io/badge/-Tested%20100%25-808080?logo=codecov&colorA=404040)](https://codecov.io/gh/ehmicky/is-json-value) [![Minified size](https://img.shields.io/bundlephobia/minzip/is-json-value?label&colorA=404040&colorB=808080&logo=webpack)](https://bundlephobia.com/package/is-json-value) [![Mastodon](https://img.shields.io/badge/-Mastodon-808080.svg?logo=mastodon&colorA=404040&logoColor=9590F9)](https://fosstodon.org/@ehmicky) [![Medium](https://img.shields.io/badge/-Medium-808080.svg?logo=medium&colorA=404040)](https://medium.com/@ehmicky) Check if a value is valid JSON. # Features - Detects [many types](#warnings) of invalid values with JSON - Returns [warning messages](#message) to throw or log - Returns invalid properties' [path](#path) and [value](#value) # Example <!-- eslint-disable symbol-description, fp/no-mutation --> ```js import isJsonValue from 'is-json-value' const input = { one: true, two: { three: Symbol() } } input.self = input // Throws due to cycle with 'self'. // Also, 'two.three' would be omitted since it has an invalid JSON type. JSON.stringify(input) const warnings = isJsonValue(input) const isValidJson = warnings.length === 0 // false console.log(warnings) // [ // { // message: 'Property "two.three" must not be a symbol.', // path: ['two', 'three'], // value: Symbol(), // reason: 'ignoredSymbolValue' // }, // { // message: 'Property "self" must not be a circular value.', // path: ['self'], // value: <ref *1> { one: true, two: [Object], self: [Circular *1] }, // reason: 'unsafeCycle' // } // ] if (!isValidJson) { // Error: Property "two.three" must not be a symbol. throw new Error(warnings[0].message) } ``` # Install ```bash npm install is-json-value ``` This package works in both Node.js >=18.18.0 and [browsers](https://raw.githubusercontent.com/ehmicky/dev-tasks/main/src/browserslist). This is an ES module. It must be loaded using [an `import` or `import()` statement](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c), not `require()`. If TypeScript is used, it must be configured to [output ES modules](https://www.typescriptlang.org/docs/handbook/esm-node.html), not CommonJS. # API ## isJsonValue(input) `input` `any`\ _Return value_: [`Warning[]`](#warning) Returns an array of [warnings](#warning). If `input` is valid to serialize as JSON, that array is empty. ### Warning Each warning is an object indicating that a specific property is invalid to serialize as JSON. The same property might have multiple warnings. #### message _Type_: `string` Warning message, like `'Property "example" must not be a symbol.'` #### path _Type_: `Array<string | symbol | number>` Path to the invalid property. Empty array if this is the top-level value. #### value _Type_: `unknown` Value of the invalid property. #### reason _Type_: `string` Reason for the warning among: - [Invalid type](#invalid-types): [`"ignoredFunction"`](#functions), [`"ignoredUndefined"`](#undefined), [`"ignoredSymbolValue"`](#symbol-values), [`"ignoredSymbolKey"`](#symbol-keys), [`"unstableInfinite"`](#nan-and-infinity), [`"unresolvedClass"`](#classes), [`"ignoredNotEnumerable"`](#non-enumerable-keys), [`"ignoredArrayProperty"`](#array-properties) - [Throws an exception](#exceptions): [`"unsafeCycle"`](#cycles), [`"unsafeBigInt"`](#bigint), [`"unsafeSize"`](#big-properties), [`"unsafeException"`](#infinite-recursion), [`"unsafeToJSON"`](#exceptions-in-tojson), [`"unsafeGetter"`](#exceptions-in-getters) # Warnings This is the list of possible warnings. ## Invalid types JSON only supports booleans, numbers, strings, arrays, objects and `null`. Any other type is omitted or transformed by `JSON.stringify()`. ### Functions ```js const invalidJson = { prop: () => {} } JSON.stringify(invalidJson) // '{}' ``` ### Undefined ```js const invalidJson = { prop: undefined } JSON.stringify(invalidJson) // '{}' ``` ### Symbol values <!-- eslint-disable symbol-description --> ```js const invalidJson = { prop: Symbol() } JSON.stringify(invalidJson) // '{}' ``` ### Symbol keys <!-- eslint-disable symbol-description --> ```js const invalidJson = { [Symbol()]: true } JSON.stringify(invalidJson) // '{}' ``` ### NaN and Infinity ```js const invalidJson = { one: Number.NaN, two: Number.POSITIVE_INFINITY } JSON.stringify(invalidJson) // '{"one":null,"two":null}' ``` ### Classes ```js const invalidJson = { prop: new Set([]) } JSON.stringify(invalidJson) // '{"prop":{}}' ``` ### Non-enumerable keys <!-- eslint-disable fp/no-mutating-methods --> ```js const invalidJson = {} Object.defineProperty(invalidJson, 'prop', { value: true, enumerable: false }) JSON.stringify(invalidJson) // '{}' ``` ### Array properties <!-- eslint-disable fp/no-mutation --> ```js const invalidJson = [] invalidJson.prop = true JSON.stringify(invalidJson) // '[]' ``` ## Exceptions `JSON.stringify()` can throw on specific properties. ### Cycles <!-- eslint-disable fp/no-mutation --> ```js const invalidJson = { prop: true } invalidJson.self = invalidJson JSON.stringify(invalidJson) // Throws: Converting circular structure to JSON ``` ### BigInt ```js const invalidJson = { prop: 0n } JSON.stringify(invalidJson) // Throws: Do not know how to serialize a BigInt ``` ### Big properties ```js const invalidJson = { prop: '\n'.repeat(5e8) } JSON.stringify(invalidJson) // Throws: Invalid string length ``` ### Infinite recursion ```js const invalidJson = { toJSON: () => ({ invalidJson }) } JSON.stringify(invalidJson) // Throws: Maximum call stack size exceeded ``` ### Exceptions in `toJSON()` ```js const invalidJson = { prop: { toJSON: () => { throw new Error('example') }, }, } JSON.stringify(invalidJson) // Throws: example ``` ### Exceptions in getters <!-- eslint-disable fp/no-get-set --> ```js const invalidJson = { get prop() { throw new Error('example') }, } JSON.stringify(invalidJson) // Throws: example ``` ### Exceptions in proxies <!-- eslint-disable fp/no-proxy --> ```js const invalidJson = new Proxy( { prop: true }, { get: () => { throw new Error('example') }, }, ) JSON.stringify(invalidJson) // Throws: example ``` # Related projects - [`safe-json-value`](https://github.com/ehmicky/safe-json-value): ⛑️ JSON serialization should never fail - [`truncate-json`](https://github.com/ehmicky/truncate-json): Truncate a JSON string - [`guess-json-indent`](https://github.com/ehmicky/guess-json-indent): Guess the indentation of a JSON string # Support For any question, _don't hesitate_ to [submit an issue on GitHub](../../issues). Everyone is welcome regardless of personal background. We enforce a [Code of conduct](CODE_OF_CONDUCT.md) in order to promote a positive and inclusive environment. # Contributing This project was made with ❤️. The simplest way to give back is by starring and sharing it online. If the documentation is unclear or has a typo, please click on the page's `Edit` button (pencil icon) and suggest a correction. If you would like to help us fix a bug or add a new feature, please check our [guidelines](CONTRIBUTING.md). Pull requests are welcome! <!-- Thanks go to our wonderful contributors: --> <!-- ALL-CONTRIBUTORS-LIST:START --> <!-- prettier-ignore --> <!-- <table><tr><td align="center"><a href="https://fosstodon.org/@ehmicky"><img src="https://avatars2.githubusercontent.com/u/8136211?v=4" width="100px;" alt="ehmicky"/><br /><sub><b>ehmicky</b></sub></a><br /><a href="https://github.com/ehmicky/is-json-value/commits?author=ehmicky" title="Code">💻</a> <a href="#design-ehmicky" title="Design">🎨</a> <a href="#ideas-ehmicky" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/ehmicky/is-json-value/commits?author=ehmicky" title="Documentation">📖</a></td></tr></table> --> <!-- ALL-CONTRIBUTORS-LIST:END -->