fast-json-stringify 6.0.0 → 6.1.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/.github/dependabot.yml +1 -1
- package/.github/workflows/ci.yml +7 -2
- package/LICENSE +5 -2
- package/README.md +50 -45
- package/benchmark/bench-cmp-branch.js +1 -1
- package/benchmark/bench-cmp-lib.js +29 -1
- package/eslint.config.js +9 -0
- package/index.js +38 -24
- package/lib/serializer.js +5 -7
- package/lib/validator.js +1 -1
- package/package.json +42 -22
- package/test/additionalProperties.test.js +20 -20
- package/test/allof.test.js +36 -40
- package/test/any.test.js +28 -28
- package/test/anyof.test.js +44 -46
- package/test/array.test.js +19 -19
- package/test/asNumber.test.js +2 -2
- package/test/basic.test.js +20 -32
- package/test/bigint.test.js +6 -6
- package/test/clean-cache.test.js +9 -7
- package/test/const.test.js +35 -35
- package/test/date.test.js +77 -77
- package/test/debug-mode.test.js +27 -27
- package/test/defaults.test.js +2 -2
- package/test/enum.test.js +3 -3
- package/test/fix-604.test.js +18 -17
- package/test/if-then-else.test.js +22 -24
- package/test/inferType.test.js +4 -4
- package/test/infinity.test.js +4 -4
- package/test/integer.test.js +21 -21
- package/test/invalidSchema.test.js +4 -8
- package/test/issue-479.test.js +2 -2
- package/test/json-schema-test-suite/README.md +1 -1
- package/test/json-schema-test-suite/draft4.test.js +3 -3
- package/test/json-schema-test-suite/draft6.test.js +3 -3
- package/test/json-schema-test-suite/draft7.test.js +3 -3
- package/test/json-schema-test-suite/util.js +6 -9
- package/test/missing-values.test.js +8 -8
- package/test/multi-type-serializer.test.js +2 -2
- package/test/nestedObjects.test.js +3 -3
- package/test/nullable.test.js +35 -35
- package/test/oneof.test.js +27 -29
- package/test/patternProperties.test.js +11 -11
- package/test/recursion.test.js +6 -6
- package/test/ref.test.js +102 -186
- package/test/regex.test.js +4 -5
- package/test/required.test.js +42 -77
- package/test/requiresAjv.test.js +34 -32
- package/test/sanitize.test.js +40 -41
- package/test/sanitize2.test.js +11 -11
- package/test/sanitize3.test.js +13 -11
- package/test/sanitize4.test.js +10 -8
- package/test/sanitize5.test.js +11 -11
- package/test/sanitize6.test.js +14 -14
- package/test/sanitize7.test.js +5 -5
- package/test/side-effect.test.js +12 -12
- package/test/standalone-mode.test.js +29 -26
- package/test/string.test.js +12 -12
- package/test/surrogate.test.js +9 -9
- package/test/toJSON.test.js +9 -9
- package/test/typebox.test.js +2 -2
- package/test/typesArray.test.js +34 -34
- package/test/unknownFormats.test.js +5 -5
- package/test/webpack.test.js +2 -2
- package/types/index.d.ts +29 -29
- package/types/index.test-d.ts +75 -74
- package/.github/workflows/benchmark.yml +0 -85
- package/.taprc +0 -7
package/.github/dependabot.yml
CHANGED
package/.github/workflows/ci.yml
CHANGED
|
@@ -4,7 +4,6 @@ on:
|
|
|
4
4
|
push:
|
|
5
5
|
branches:
|
|
6
6
|
- main
|
|
7
|
-
- master
|
|
8
7
|
- next
|
|
9
8
|
- 'v*'
|
|
10
9
|
paths-ignore:
|
|
@@ -15,9 +14,15 @@ on:
|
|
|
15
14
|
- 'docs/**'
|
|
16
15
|
- '*.md'
|
|
17
16
|
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
18
20
|
jobs:
|
|
19
21
|
test:
|
|
20
|
-
|
|
22
|
+
permissions:
|
|
23
|
+
contents: write
|
|
24
|
+
pull-requests: write
|
|
25
|
+
uses: fastify/workflows/.github/workflows/plugins-ci.yml@v5
|
|
21
26
|
with:
|
|
22
27
|
license-check: true
|
|
23
28
|
lint: true
|
package/LICENSE
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2016-
|
|
3
|
+
Copyright (c) 2016-present Matteo Collina
|
|
4
|
+
Copyright (c) 2016-present The Fastify team
|
|
5
|
+
|
|
6
|
+
The Fastify team members are listed at https://github.com/fastify/fastify#team.
|
|
4
7
|
|
|
5
8
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
9
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# fast-json-stringify
|
|
2
2
|
|
|
3
|
-
](https://github.com/fastify/fast-json-stringify/actions/workflows/ci.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/fast-json-stringify)
|
|
5
|
-
[](https://github.com/neostandard/neostandard)
|
|
6
6
|
[](https://www.npmjs.com/package/fast-json-stringify)
|
|
7
7
|
|
|
8
|
-
|
|
9
8
|
__fast-json-stringify__ is significantly faster than `JSON.stringify()` for small payloads.
|
|
10
9
|
Its performance advantage shrinks as your payload grows.
|
|
11
10
|
It pairs well with [__flatstr__](https://www.npmjs.com/package/flatstr), which triggers a V8 optimization that improves performance when eventually converting the string to a `Buffer`.
|
|
@@ -18,37 +17,43 @@ fast-json-stringify requires a [JSON Schema Draft 7](https://json-schema.org/spe
|
|
|
18
17
|
##### Benchmarks
|
|
19
18
|
|
|
20
19
|
- Machine: `EX41S-SSD, Intel Core i7, 4Ghz, 64GB RAM, 4C/8T, SSD`.
|
|
21
|
-
- Node.js `
|
|
20
|
+
- Node.js `v22.14.0`
|
|
22
21
|
|
|
23
22
|
```
|
|
24
|
-
FJS creation x
|
|
25
|
-
CJS creation x
|
|
26
|
-
AJV Serialize creation x
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
fast-json-stringify array
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
compile-json-stringify
|
|
48
|
-
AJV Serialize
|
|
49
|
-
JSON
|
|
50
|
-
fast-json-stringify
|
|
51
|
-
|
|
23
|
+
FJS creation x 9,696 ops/sec ±0.77% (94 runs sampled)
|
|
24
|
+
CJS creation x 197,267 ops/sec ±0.22% (95 runs sampled)
|
|
25
|
+
AJV Serialize creation x 48,302,927 ops/sec ±2.09% (90 runs sampled)
|
|
26
|
+
json-accelerator creation x 668,430 ops/sec ±0.43% (95 runs sampled)
|
|
27
|
+
JSON.stringify array x 7,924 ops/sec ±0.11% (98 runs sampled)
|
|
28
|
+
fast-json-stringify array default x 7,183 ops/sec ±0.09% (97 runs sampled)
|
|
29
|
+
json-accelerator array x 5,762 ops/sec ±0.27% (99 runs sampled)
|
|
30
|
+
fast-json-stringify array json-stringify x 7,171 ops/sec ±0.17% (97 runs sampled)
|
|
31
|
+
compile-json-stringify array x 6,889 ops/sec ±0.41% (96 runs sampled)
|
|
32
|
+
AJV Serialize array x 6,945 ops/sec ±0.17% (98 runs sampled)
|
|
33
|
+
JSON.stringify large array x 331 ops/sec ±0.17% (93 runs sampled)
|
|
34
|
+
fast-json-stringify large array default x 208 ops/sec ±0.21% (91 runs sampled)
|
|
35
|
+
fast-json-stringify large array json-stringify x 330 ops/sec ±0.17% (93 runs sampled)
|
|
36
|
+
compile-json-stringify large array x 318 ops/sec ±0.11% (90 runs sampled)
|
|
37
|
+
AJV Serialize large array x 114 ops/sec ±0.27% (74 runs sampled)
|
|
38
|
+
JSON.stringify long string x 13,452 ops/sec ±0.15% (99 runs sampled)
|
|
39
|
+
fast-json-stringify long string x 13,454 ops/sec ±0.10% (99 runs sampled)
|
|
40
|
+
json-accelerator long string x 13,439 ops/sec ±0.09% (98 runs sampled)
|
|
41
|
+
compile-json-stringify long string x 13,380 ops/sec ±0.12% (100 runs sampled)
|
|
42
|
+
AJV Serialize long string x 21,932 ops/sec ±0.06% (99 runs sampled)
|
|
43
|
+
JSON.stringify short string x 12,114,052 ops/sec ±0.59% (97 runs sampled)
|
|
44
|
+
fast-json-stringify short string x 29,408,175 ops/sec ±1.12% (91 runs sampled)
|
|
45
|
+
json-accelerator short string x 29,431,694 ops/sec ±1.05% (93 runs sampled)
|
|
46
|
+
compile-json-stringify short string x 24,740,338 ops/sec ±1.02% (91 runs sampled)
|
|
47
|
+
AJV Serialize short string x 17,841,869 ops/sec ±0.90% (91 runs sampled)
|
|
48
|
+
JSON.stringify obj x 4,577,494 ops/sec ±0.25% (94 runs sampled)
|
|
49
|
+
fast-json-stringify obj x 7,291,157 ops/sec ±0.40% (97 runs sampled)
|
|
50
|
+
json-accelerator obj x 6,473,194 ops/sec ±0.31% (99 runs sampled)
|
|
51
|
+
compile-json-stringify obj x 14,724,935 ops/sec ±0.50% (96 runs sampled)
|
|
52
|
+
AJV Serialize obj x 8,782,944 ops/sec ±0.45% (93 runs sampled)
|
|
53
|
+
JSON stringify date x 803,522 ops/sec ±0.47% (98 runs sampled)
|
|
54
|
+
fast-json-stringify date format x 1,117,776 ops/sec ±0.69% (95 runs sampled)
|
|
55
|
+
json-accelerate date format x 1,122,419 ops/sec ±0.20% (97 runs sampled)
|
|
56
|
+
compile-json-stringify date format x 803,214 ops/sec ±0.23% (97 runs sampled)
|
|
52
57
|
```
|
|
53
58
|
|
|
54
59
|
#### Table of contents:
|
|
@@ -70,7 +75,7 @@ compile-json-stringify date format x 1,125,735 ops/sec ±0.19% (98 runs sampled)
|
|
|
70
75
|
- <a href="#security">`Security Notice`</a>
|
|
71
76
|
- <a href="#debug">`Debug Mode`</a>
|
|
72
77
|
- <a href="#standalone">`Standalone Mode`</a>
|
|
73
|
-
- <a href="#
|
|
78
|
+
- <a href="#acknowledgments">`Acknowledgments`</a>
|
|
74
79
|
- <a href="#license">`License`</a>
|
|
75
80
|
|
|
76
81
|
|
|
@@ -111,7 +116,7 @@ console.log(stringify({
|
|
|
111
116
|
<a name="options"></a>
|
|
112
117
|
## Options
|
|
113
118
|
|
|
114
|
-
Optionally, you may provide to `fast-json-stringify` an option object as second parameter:
|
|
119
|
+
Optionally, you may provide to `fast-json-stringify` an option object as the second parameter:
|
|
115
120
|
|
|
116
121
|
```js
|
|
117
122
|
const fastJson = require('fast-json-stringify')
|
|
@@ -165,7 +170,7 @@ And nested ones, too.
|
|
|
165
170
|
| `date` | `2020-04-03` |
|
|
166
171
|
| `time` | `09:11:08` |
|
|
167
172
|
|
|
168
|
-
**Note**: In the case of string formatted Date and not Date Object, there will be no manipulation on it. It should be properly formatted.
|
|
173
|
+
**Note**: In the case of a string formatted Date and not Date Object, there will be no manipulation on it. It should be properly formatted.
|
|
169
174
|
|
|
170
175
|
Example with a Date object:
|
|
171
176
|
|
|
@@ -290,7 +295,7 @@ console.log(stringify(obj)) // '{"matchfoo":"42","otherfoo":"str","matchnum":3,"
|
|
|
290
295
|
*additionalProperties* must be an object or a boolean, declared in this way: `{ type: 'type' }`.
|
|
291
296
|
*additionalProperties* will work only for the properties that are not explicitly listed in the *properties* and *patternProperties* objects.
|
|
292
297
|
|
|
293
|
-
If *additionalProperties* is not present or is set to `false`, every property that is not explicitly listed in the *properties* and *patternProperties* objects
|
|
298
|
+
If *additionalProperties* is not present or is set to `false`, every property that is not explicitly listed in the *properties* and *patternProperties* objects will be ignored, as described in <a href="#missingFields">Missing fields</a>.
|
|
294
299
|
Missing fields are ignored to avoid having to rewrite objects before serializing. However, other schema rules would throw in similar situations.
|
|
295
300
|
If *additionalProperties* is set to `true`, it will be used by `JSON.stringify` to stringify the additional properties. If you want to achieve maximum performance, we strongly encourage you to use a fixed schema where possible.
|
|
296
301
|
The additional properties will always be serialized at the end of the object.
|
|
@@ -543,12 +548,12 @@ const stringify = fastJson(schema, { schema: externalSchema })
|
|
|
543
548
|
|
|
544
549
|
<a name="long"></a>
|
|
545
550
|
#### Long integers
|
|
546
|
-
By default the library will handle automatically [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
|
|
551
|
+
By default, the library will handle automatically [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
|
|
547
552
|
|
|
548
553
|
<a name="integer"></a>
|
|
549
554
|
#### Integers
|
|
550
555
|
The `type: integer` property will be truncated if a floating point is provided.
|
|
551
|
-
You can customize this
|
|
556
|
+
You can customize this behavior with the `rounding` option that will accept [`round`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round), [`ceil`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/ceil), [`floor`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor), or [`trunc`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc). Default is `trunc`:
|
|
552
557
|
|
|
553
558
|
```js
|
|
554
559
|
const stringify = fastJson(schema, { rounding: 'ceil' })
|
|
@@ -650,8 +655,8 @@ const stringify = fastJson({
|
|
|
650
655
|
|
|
651
656
|
##### Benchmarks
|
|
652
657
|
|
|
653
|
-
For reference, here
|
|
654
|
-
mechanisms. Benchmarks conducted on an old machine.
|
|
658
|
+
For reference, here are some benchmarks for comparison over the three
|
|
659
|
+
mechanisms. Benchmarks were conducted on an old machine.
|
|
655
660
|
|
|
656
661
|
- Machine: `ST1000LM024 HN-M 1TB HDD, Intel Core i7-3610QM @ 2.3GHz, 12GB RAM, 4C/8T`.
|
|
657
662
|
- Node.js `v16.13.1`
|
|
@@ -678,7 +683,7 @@ expose your application to remote attacks.
|
|
|
678
683
|
|
|
679
684
|
Users are responsible for sending trusted data. `fast-json-stringify` guarantees that you will get
|
|
680
685
|
a valid output only if your input matches the schema or can be coerced to the schema. If your input
|
|
681
|
-
doesn't match the schema, you will get undefined behavior.
|
|
686
|
+
doesn't match the schema, you will get undefined behavior.
|
|
682
687
|
|
|
683
688
|
<a name="debug"></a>
|
|
684
689
|
### Debug Mode
|
|
@@ -699,7 +704,7 @@ const debugCompiled = fastJson({
|
|
|
699
704
|
|
|
700
705
|
console.log(debugCompiled) // it is a object contain code, ajv instance
|
|
701
706
|
const rawString = debugCompiled.code // it is the generated code
|
|
702
|
-
console.log(rawString)
|
|
707
|
+
console.log(rawString)
|
|
703
708
|
|
|
704
709
|
const stringify = fastJson.restore(debugCompiled) // use the generated string to get back the `stringify` function
|
|
705
710
|
console.log(stringify({ firstName: 'Foo', surname: 'bar' })) // '{"firstName":"Foo"}'
|
|
@@ -728,12 +733,12 @@ const stringify = require('stringify.js')
|
|
|
728
733
|
console.log(stringify({ firstName: 'Foo', surname: 'bar' })) // '{"firstName":"Foo"}'
|
|
729
734
|
```
|
|
730
735
|
|
|
731
|
-
<a name="
|
|
732
|
-
##
|
|
736
|
+
<a name="acknowledgments"></a>
|
|
737
|
+
## Acknowledgments
|
|
733
738
|
|
|
734
739
|
This project was kindly sponsored by [nearForm](https://nearform.com).
|
|
735
740
|
|
|
736
741
|
<a name="license"></a>
|
|
737
742
|
## License
|
|
738
743
|
|
|
739
|
-
MIT
|
|
744
|
+
Licensed under [MIT](./LICENSE).
|
|
@@ -8,7 +8,7 @@ const simpleGit = require('simple-git')
|
|
|
8
8
|
const git = simpleGit(process.cwd())
|
|
9
9
|
|
|
10
10
|
const COMMAND = 'npm run bench'
|
|
11
|
-
const DEFAULT_BRANCH = '
|
|
11
|
+
const DEFAULT_BRANCH = 'main'
|
|
12
12
|
const PERCENT_THRESHOLD = 5
|
|
13
13
|
const greyColor = '\x1b[30m'
|
|
14
14
|
const redColor = '\x1b[31m'
|
|
@@ -118,6 +118,12 @@ const ajvSerialize = ajv.compileSerializer(schemaAJVJTD)
|
|
|
118
118
|
const ajvSerializeArray = ajv.compileSerializer(arraySchemaAJVJTD)
|
|
119
119
|
const ajvSerializeString = ajv.compileSerializer({ type: 'string' })
|
|
120
120
|
|
|
121
|
+
const { createAccelerator } = require('json-accelerator')
|
|
122
|
+
const accelStringify = createAccelerator(schema)
|
|
123
|
+
const accelArray = createAccelerator(arraySchema)
|
|
124
|
+
const accelDate = FJS(dateFormatSchema)
|
|
125
|
+
const accelString = FJS({ type: 'string' })
|
|
126
|
+
|
|
121
127
|
const getRandomString = (length) => {
|
|
122
128
|
if (!Number.isInteger(length)) {
|
|
123
129
|
throw new Error('Expected integer length')
|
|
@@ -134,7 +140,6 @@ const getRandomString = (length) => {
|
|
|
134
140
|
return result[0].toUpperCase() + result.slice(1)
|
|
135
141
|
}
|
|
136
142
|
|
|
137
|
-
// eslint-disable-next-line
|
|
138
143
|
for (let i = 0; i < STR_LEN; i++) {
|
|
139
144
|
largeArray[i] = {
|
|
140
145
|
firstName: getRandomString(8),
|
|
@@ -171,6 +176,9 @@ suite.add('CJS creation', function () {
|
|
|
171
176
|
suite.add('AJV Serialize creation', function () {
|
|
172
177
|
ajv.compileSerializer(schemaAJVJTD)
|
|
173
178
|
})
|
|
179
|
+
suite.add('json-accelerator creation', function () {
|
|
180
|
+
createAccelerator(schema)
|
|
181
|
+
})
|
|
174
182
|
|
|
175
183
|
suite.add('JSON.stringify array', function () {
|
|
176
184
|
JSON.stringify(multiArray)
|
|
@@ -180,6 +188,10 @@ suite.add('fast-json-stringify array default', function () {
|
|
|
180
188
|
stringifyArrayDefault(multiArray)
|
|
181
189
|
})
|
|
182
190
|
|
|
191
|
+
suite.add('json-accelerator array', function () {
|
|
192
|
+
accelArray(multiArray)
|
|
193
|
+
})
|
|
194
|
+
|
|
183
195
|
suite.add('fast-json-stringify array json-stringify', function () {
|
|
184
196
|
stringifyArrayJSONStringify(multiArray)
|
|
185
197
|
})
|
|
@@ -220,6 +232,10 @@ suite.add('fast-json-stringify long string', function () {
|
|
|
220
232
|
stringifyString(str)
|
|
221
233
|
})
|
|
222
234
|
|
|
235
|
+
suite.add('json-accelerator long string', function () {
|
|
236
|
+
stringifyString(str)
|
|
237
|
+
})
|
|
238
|
+
|
|
223
239
|
suite.add('compile-json-stringify long string', function () {
|
|
224
240
|
CJSStringifyString(str)
|
|
225
241
|
})
|
|
@@ -236,6 +252,10 @@ suite.add('fast-json-stringify short string', function () {
|
|
|
236
252
|
stringifyString('hello world')
|
|
237
253
|
})
|
|
238
254
|
|
|
255
|
+
suite.add('json-accelerator short string', function () {
|
|
256
|
+
accelString('hello world')
|
|
257
|
+
})
|
|
258
|
+
|
|
239
259
|
suite.add('compile-json-stringify short string', function () {
|
|
240
260
|
CJSStringifyString('hello world')
|
|
241
261
|
})
|
|
@@ -252,6 +272,10 @@ suite.add('fast-json-stringify obj', function () {
|
|
|
252
272
|
stringify(obj)
|
|
253
273
|
})
|
|
254
274
|
|
|
275
|
+
suite.add('json-accelerator obj', function () {
|
|
276
|
+
accelStringify(obj)
|
|
277
|
+
})
|
|
278
|
+
|
|
255
279
|
suite.add('compile-json-stringify obj', function () {
|
|
256
280
|
CJSStringify(obj)
|
|
257
281
|
})
|
|
@@ -268,6 +292,10 @@ suite.add('fast-json-stringify date format', function () {
|
|
|
268
292
|
stringifyDate(date)
|
|
269
293
|
})
|
|
270
294
|
|
|
295
|
+
suite.add('json-accelerate date format', function () {
|
|
296
|
+
accelDate(date)
|
|
297
|
+
})
|
|
298
|
+
|
|
271
299
|
suite.add('compile-json-stringify date format', function () {
|
|
272
300
|
CJSStringifyDate(date)
|
|
273
301
|
})
|
package/eslint.config.js
ADDED
package/index.js
CHANGED
|
@@ -15,6 +15,21 @@ const SINGLE_TICK = /'/g
|
|
|
15
15
|
let largeArraySize = 2e4
|
|
16
16
|
let largeArrayMechanism = 'default'
|
|
17
17
|
|
|
18
|
+
const serializerFns = `
|
|
19
|
+
const {
|
|
20
|
+
asString,
|
|
21
|
+
asNumber,
|
|
22
|
+
asBoolean,
|
|
23
|
+
asDateTime,
|
|
24
|
+
asDate,
|
|
25
|
+
asTime,
|
|
26
|
+
asUnsafeString
|
|
27
|
+
} = serializer
|
|
28
|
+
|
|
29
|
+
const asInteger = serializer.asInteger.bind(serializer)
|
|
30
|
+
|
|
31
|
+
`
|
|
32
|
+
|
|
18
33
|
const validRoundingMethods = [
|
|
19
34
|
'floor',
|
|
20
35
|
'ceil',
|
|
@@ -141,6 +156,7 @@ function build (schema, options) {
|
|
|
141
156
|
const code = buildValue(context, location, 'input')
|
|
142
157
|
|
|
143
158
|
let contextFunctionCode = `
|
|
159
|
+
${serializerFns}
|
|
144
160
|
const JSON_STR_BEGIN_OBJECT = '{'
|
|
145
161
|
const JSON_STR_END_OBJECT = '}'
|
|
146
162
|
const JSON_STR_BEGIN_ARRAY = '['
|
|
@@ -252,20 +268,16 @@ const numberKeywords = [
|
|
|
252
268
|
* https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6
|
|
253
269
|
*/
|
|
254
270
|
function inferTypeByKeyword (schema) {
|
|
255
|
-
|
|
256
|
-
for (var keyword of objectKeywords) {
|
|
271
|
+
for (const keyword of objectKeywords) {
|
|
257
272
|
if (keyword in schema) return 'object'
|
|
258
273
|
}
|
|
259
|
-
|
|
260
|
-
for (var keyword of arrayKeywords) {
|
|
274
|
+
for (const keyword of arrayKeywords) {
|
|
261
275
|
if (keyword in schema) return 'array'
|
|
262
276
|
}
|
|
263
|
-
|
|
264
|
-
for (var keyword of stringKeywords) {
|
|
277
|
+
for (const keyword of stringKeywords) {
|
|
265
278
|
if (keyword in schema) return 'string'
|
|
266
279
|
}
|
|
267
|
-
|
|
268
|
-
for (var keyword of numberKeywords) {
|
|
280
|
+
for (const keyword of numberKeywords) {
|
|
269
281
|
if (keyword in schema) return 'number'
|
|
270
282
|
}
|
|
271
283
|
return schema.type
|
|
@@ -296,7 +308,7 @@ function buildExtraObjectPropertiesSerializer (context, location, addComma) {
|
|
|
296
308
|
code += `
|
|
297
309
|
if (/${propertyKey.replace(/\\*\//g, '\\/')}/.test(key)) {
|
|
298
310
|
${addComma}
|
|
299
|
-
json +=
|
|
311
|
+
json += asString(key) + JSON_STR_COLONS
|
|
300
312
|
${buildValue(context, propertyLocation, 'value')}
|
|
301
313
|
continue
|
|
302
314
|
}
|
|
@@ -311,13 +323,13 @@ function buildExtraObjectPropertiesSerializer (context, location, addComma) {
|
|
|
311
323
|
if (additionalPropertiesSchema === true) {
|
|
312
324
|
code += `
|
|
313
325
|
${addComma}
|
|
314
|
-
json +=
|
|
326
|
+
json += asString(key) + JSON_STR_COLONS + JSON.stringify(value)
|
|
315
327
|
`
|
|
316
328
|
} else {
|
|
317
329
|
const propertyLocation = location.getPropertyLocation('additionalProperties')
|
|
318
330
|
code += `
|
|
319
331
|
${addComma}
|
|
320
|
-
json +=
|
|
332
|
+
json += asString(key) + JSON_STR_COLONS
|
|
321
333
|
${buildValue(context, propertyLocation, 'value')}
|
|
322
334
|
`
|
|
323
335
|
}
|
|
@@ -569,7 +581,7 @@ function buildArray (context, location) {
|
|
|
569
581
|
const tmpRes = buildValue(context, itemsLocation.getPropertyLocation(i), 'value')
|
|
570
582
|
functionCode += `
|
|
571
583
|
if (${i} < arrayLength) {
|
|
572
|
-
if (${buildArrayTypeCondition(item.type,
|
|
584
|
+
if (${buildArrayTypeCondition(item.type, 'value')}) {
|
|
573
585
|
${tmpRes}
|
|
574
586
|
if (${i} < arrayEnd) {
|
|
575
587
|
json += JSON_STR_COMMA
|
|
@@ -584,16 +596,18 @@ function buildArray (context, location) {
|
|
|
584
596
|
if (schema.additionalItems) {
|
|
585
597
|
functionCode += `
|
|
586
598
|
for (let i = ${itemsSchema.length}; i < arrayLength; i++) {
|
|
587
|
-
|
|
599
|
+
value = obj[i]
|
|
600
|
+
json += JSON.stringify(value)
|
|
588
601
|
if (i < arrayEnd) {
|
|
589
602
|
json += JSON_STR_COMMA
|
|
590
603
|
}
|
|
591
604
|
}`
|
|
592
605
|
}
|
|
593
606
|
} else {
|
|
594
|
-
const code = buildValue(context, itemsLocation, '
|
|
607
|
+
const code = buildValue(context, itemsLocation, 'value')
|
|
595
608
|
functionCode += `
|
|
596
609
|
for (let i = 0; i < arrayLength; i++) {
|
|
610
|
+
value = obj[i]
|
|
597
611
|
${code}
|
|
598
612
|
if (i < arrayEnd) {
|
|
599
613
|
json += JSON_STR_COMMA
|
|
@@ -733,13 +747,13 @@ function buildSingleTypeSerializer (context, location, input) {
|
|
|
733
747
|
return 'json += JSON_STR_NULL'
|
|
734
748
|
case 'string': {
|
|
735
749
|
if (schema.format === 'date-time') {
|
|
736
|
-
return `json +=
|
|
750
|
+
return `json += asDateTime(${input})`
|
|
737
751
|
} else if (schema.format === 'date') {
|
|
738
|
-
return `json +=
|
|
752
|
+
return `json += asDate(${input})`
|
|
739
753
|
} else if (schema.format === 'time') {
|
|
740
|
-
return `json +=
|
|
754
|
+
return `json += asTime(${input})`
|
|
741
755
|
} else if (schema.format === 'unsafe') {
|
|
742
|
-
return `json +=
|
|
756
|
+
return `json += asUnsafeString(${input})`
|
|
743
757
|
} else {
|
|
744
758
|
return `
|
|
745
759
|
if (typeof ${input} !== 'string') {
|
|
@@ -748,22 +762,22 @@ function buildSingleTypeSerializer (context, location, input) {
|
|
|
748
762
|
} else if (${input} instanceof Date) {
|
|
749
763
|
json += JSON_STR_QUOTE + ${input}.toISOString() + JSON_STR_QUOTE
|
|
750
764
|
} else if (${input} instanceof RegExp) {
|
|
751
|
-
json +=
|
|
765
|
+
json += asString(${input}.source)
|
|
752
766
|
} else {
|
|
753
|
-
json +=
|
|
767
|
+
json += asString(${input}.toString())
|
|
754
768
|
}
|
|
755
769
|
} else {
|
|
756
|
-
json +=
|
|
770
|
+
json += asString(${input})
|
|
757
771
|
}
|
|
758
772
|
`
|
|
759
773
|
}
|
|
760
774
|
}
|
|
761
775
|
case 'integer':
|
|
762
|
-
return `json +=
|
|
776
|
+
return `json += asInteger(${input})`
|
|
763
777
|
case 'number':
|
|
764
|
-
return `json +=
|
|
778
|
+
return `json += asNumber(${input})`
|
|
765
779
|
case 'boolean':
|
|
766
|
-
return `json +=
|
|
780
|
+
return `json += asBoolean(${input})`
|
|
767
781
|
case 'object': {
|
|
768
782
|
const funcName = buildObject(context, location)
|
|
769
783
|
return `json += ${funcName}(${input})`
|
package/lib/serializer.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
// eslint-disable-next-line
|
|
4
|
-
const STR_ESCAPE = /[\u0000-\u001f\u0022\u005c\ud800-\udfff]/
|
|
5
|
-
|
|
6
3
|
module.exports = class Serializer {
|
|
7
4
|
constructor (options) {
|
|
8
5
|
switch (options && options.rounding) {
|
|
@@ -92,7 +89,9 @@ module.exports = class Serializer {
|
|
|
92
89
|
|
|
93
90
|
asString (str) {
|
|
94
91
|
const len = str.length
|
|
95
|
-
if (len
|
|
92
|
+
if (len === 0) {
|
|
93
|
+
return '""'
|
|
94
|
+
} else if (len < 42) {
|
|
96
95
|
// magically escape strings for json
|
|
97
96
|
// relying on their charCodeAt
|
|
98
97
|
// everything below 32 needs JSON.stringify()
|
|
@@ -102,8 +101,7 @@ module.exports = class Serializer {
|
|
|
102
101
|
let result = ''
|
|
103
102
|
let last = -1
|
|
104
103
|
let point = 255
|
|
105
|
-
|
|
106
|
-
for (var i = 0; i < len; i++) {
|
|
104
|
+
for (let i = 0; i < len; i++) {
|
|
107
105
|
point = str.charCodeAt(i)
|
|
108
106
|
if (
|
|
109
107
|
point === 0x22 || // '"'
|
|
@@ -118,7 +116,7 @@ module.exports = class Serializer {
|
|
|
118
116
|
}
|
|
119
117
|
}
|
|
120
118
|
return (last === -1 && ('"' + str + '"')) || ('"' + result + str.slice(last) + '"')
|
|
121
|
-
} else if (len < 5000 &&
|
|
119
|
+
} else if (len < 5000 && str.isWellFormed()) {
|
|
122
120
|
// Only use the regular expression for shorter input. The overhead is otherwise too much.
|
|
123
121
|
return '"' + str + '"'
|
|
124
122
|
} else {
|
package/lib/validator.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fast-json-stringify",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "Stringify your JSON at max speed",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -10,16 +10,12 @@
|
|
|
10
10
|
"bench:cmp": "node ./benchmark/bench-cmp-branch.js",
|
|
11
11
|
"bench:cmp:ci": "node ./benchmark/bench-cmp-branch.js --ci",
|
|
12
12
|
"benchmark": "node ./benchmark/bench-cmp-lib.js",
|
|
13
|
-
"lint": "
|
|
14
|
-
"lint:fix": "
|
|
13
|
+
"lint": "eslint",
|
|
14
|
+
"lint:fix": "eslint --fix",
|
|
15
15
|
"test:typescript": "tsd",
|
|
16
|
-
"test:unit": "
|
|
16
|
+
"test:unit": "c8 node --test",
|
|
17
17
|
"test": "npm run test:unit && npm run test:typescript"
|
|
18
18
|
},
|
|
19
|
-
"precommit": [
|
|
20
|
-
"lint",
|
|
21
|
-
"test"
|
|
22
|
-
],
|
|
23
19
|
"repository": {
|
|
24
20
|
"type": "git",
|
|
25
21
|
"url": "git+https://github.com/fastify/fast-json-stringify.git"
|
|
@@ -31,38 +27,62 @@
|
|
|
31
27
|
"fast"
|
|
32
28
|
],
|
|
33
29
|
"author": "Matteo Collina <hello@matteocollina.com>",
|
|
30
|
+
"contributors": [
|
|
31
|
+
{
|
|
32
|
+
"name": "Tomas Della Vedova",
|
|
33
|
+
"url": "http://delved.org"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "Aras Abbasi",
|
|
37
|
+
"email": "aras.abbasi@gmail.com"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "Manuel Spigolon",
|
|
41
|
+
"email": "behemoth89@gmail.com"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "Frazer Smith",
|
|
45
|
+
"email": "frazer.dev@icloud.com",
|
|
46
|
+
"url": "https://github.com/fdawgs"
|
|
47
|
+
}
|
|
48
|
+
],
|
|
34
49
|
"license": "MIT",
|
|
35
50
|
"bugs": {
|
|
36
51
|
"url": "https://github.com/fastify/fast-json-stringify/issues"
|
|
37
52
|
},
|
|
38
53
|
"homepage": "https://github.com/fastify/fast-json-stringify#readme",
|
|
54
|
+
"funding": [
|
|
55
|
+
{
|
|
56
|
+
"type": "github",
|
|
57
|
+
"url": "https://github.com/sponsors/fastify"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"type": "opencollective",
|
|
61
|
+
"url": "https://opencollective.com/fastify"
|
|
62
|
+
}
|
|
63
|
+
],
|
|
39
64
|
"devDependencies": {
|
|
40
|
-
"@
|
|
41
|
-
"@sinclair/typebox": "^0.32.15",
|
|
65
|
+
"@sinclair/typebox": "^0.34.3",
|
|
42
66
|
"benchmark": "^2.1.4",
|
|
67
|
+
"c8": "^10.1.2",
|
|
43
68
|
"cli-select": "^1.1.2",
|
|
44
69
|
"compile-json-stringify": "^0.1.2",
|
|
70
|
+
"eslint": "^9.17.0",
|
|
45
71
|
"fast-json-stringify": ".",
|
|
46
72
|
"is-my-json-valid": "^2.20.6",
|
|
73
|
+
"json-accelerator": "^0.0.2",
|
|
74
|
+
"neostandard": "^0.12.0",
|
|
47
75
|
"simple-git": "^3.23.0",
|
|
48
|
-
"
|
|
49
|
-
"tap": "^19.2.5",
|
|
50
|
-
"tsd": "^0.31.0",
|
|
76
|
+
"tsd": "^0.32.0",
|
|
51
77
|
"webpack": "^5.90.3"
|
|
52
78
|
},
|
|
53
79
|
"dependencies": {
|
|
54
|
-
"@fastify/merge-json-schemas": "^0.
|
|
80
|
+
"@fastify/merge-json-schemas": "^0.2.0",
|
|
55
81
|
"ajv": "^8.12.0",
|
|
56
82
|
"ajv-formats": "^3.0.1",
|
|
57
|
-
"fast-
|
|
58
|
-
"
|
|
59
|
-
"json-schema-ref-resolver": "^1.0.1",
|
|
83
|
+
"fast-uri": "^3.0.0",
|
|
84
|
+
"json-schema-ref-resolver": "^3.0.0",
|
|
60
85
|
"rfdc": "^1.2.0"
|
|
61
86
|
},
|
|
62
|
-
"standard": {
|
|
63
|
-
"ignore": [
|
|
64
|
-
"schema-validator.js"
|
|
65
|
-
]
|
|
66
|
-
},
|
|
67
87
|
"runkitExampleFilename": "./examples/example.js"
|
|
68
88
|
}
|