1 | # destr
|
2 |
|
3 | > A faster, secure and convenient alternative for [`JSON.parse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse):
|
4 |
|
5 | [![npm version][npm-v-src]][npm-v-href]
|
6 | [![npm downloads][npm-d-src]][npm-d-href]
|
7 | [![bundle phobia][bundlephobia-src]][bundlephobia-href]
|
8 |
|
9 | ## Usage
|
10 |
|
11 | ### Node.js
|
12 |
|
13 | Install using npm or yarn:
|
14 |
|
15 | ```bash
|
16 | npm i destr
|
17 | # or
|
18 | yarn add destr
|
19 | ```
|
20 |
|
21 | Import into your Node.js project:
|
22 |
|
23 | ```js
|
24 | // CommonJS
|
25 | const destr = require('destr')
|
26 |
|
27 | // ESM
|
28 | import destr from 'destr'
|
29 | ```
|
30 |
|
31 | ### Deno
|
32 |
|
33 | ```js
|
34 | import destr from 'https://cdn.jsdelivr.net/gh/nuxt-contrib/destr/src/index.ts'
|
35 |
|
36 | console.log(destr('{ "deno": "yay" }'))
|
37 | ```
|
38 |
|
39 | ## Why?
|
40 |
|
41 | ⚠️ Before reading cool features, please note that `destr` is not always faster! When parsing a standard JSON string it is about **3 times slower** mainly because of transform to avoid [prototype pollution](https://hueniverse.com/a-tale-of-prototype-poisoning-2610fa170061) which can lead to serious security issues if not being sanetized.
|
42 |
|
43 | In the other words, `destr` is better when input is not always a json string or from untrsuted source like request body.
|
44 |
|
45 | **Fast fallback to input if is not string:**
|
46 |
|
47 | ```js
|
48 | // Uncaught SyntaxError: Unexpected token u in JSON at position 0
|
49 | JSON.parse()
|
50 |
|
51 | // undefined
|
52 | destr()
|
53 | ```
|
54 |
|
55 | ```js
|
56 | // JSON.parse x 5,363,773 ops/sec ±0.31% (96 runs sampled)
|
57 | JSON.parse(3.14159265359)
|
58 |
|
59 | // destr x 660,537,795 ops/sec ±0.06% (86 runs sampled)
|
60 | destr(3.14159265359)
|
61 | ```
|
62 |
|
63 | **Fast lookup for known string values:**
|
64 |
|
65 | ```js
|
66 | // Uncaught SyntaxError: Unexpected token T in JSON at position 0
|
67 | JSON.parse('TRUE')
|
68 |
|
69 | // true
|
70 | destr('TRUE')
|
71 | ```
|
72 |
|
73 | ```js
|
74 | // JSON.parse x 10,432,994 ops/sec ±0.23% (94 runs sampled)
|
75 | JSON.parse('true')
|
76 |
|
77 | // destr x 652,107,152 ops/sec ±0.11% (94 runs sampled
|
78 | destr('true')
|
79 | ```
|
80 |
|
81 | **Fallback to original value if parse fails (empty or any plain string):**
|
82 |
|
83 | ```js
|
84 | // Uncaught SyntaxError: Unexpected token s in JSON at position 0
|
85 | // JSON.parse (try-catch) x 248,749 ops/sec ±1.66% (93 runs sampled)
|
86 | JSON.parse('salam')
|
87 |
|
88 | // destr x 32,415,523 ops/sec ±0.57% (94 runs sampled)
|
89 | destr('salam')
|
90 | ```
|
91 |
|
92 | **Avoid prototype pollution:**
|
93 |
|
94 | ```js
|
95 | const input = '{ "user": { "__proto__": { "isAdmin": true } } }'
|
96 |
|
97 | // { user: { __proto__: { isAdmin: true } } }
|
98 | JSON.parse(input)
|
99 |
|
100 | // { user: {} }
|
101 | destr(input)
|
102 | ```
|
103 |
|
104 | **Better types:**
|
105 |
|
106 | ```ts
|
107 | interface JSON {
|
108 | parse(text: string, reviver?: (this: any, key: string, value: any) => any): any
|
109 | }
|
110 | ```
|
111 |
|
112 | ```ts
|
113 | function destr(val: string | any): DestrValue
|
114 | ```
|
115 |
|
116 | ## License
|
117 |
|
118 | MIT. Made with 💖
|
119 |
|
120 |
|
121 | [npm-v-src]: https://img.shields.io/npm/v/destr?style=flat-square
|
122 | [npm-v-href]: https://npmjs.com/package/destr
|
123 |
|
124 | [npm-d-src]: https://img.shields.io/npm/dm/destr?style=flat-square
|
125 | [npm-d-href]: https://npmjs.com/package/destr
|
126 |
|
127 | [github-actions-src]: https://img.shields.io/github/workflow/status/nuxt-contrib/destr/ci/master?style=flat-square
|
128 | [github-actions-href]: https://github.com/nuxt-contrib/destr/actions?query=workflow%3Aci
|
129 |
|
130 | [bundlephobia-src]: https://img.shields.io/bundlephobia/min/destr?style=flat-square
|
131 | [bundlephobia-href]: https://bundlephobia.com/result?p=destr
|