fast-json-stringify 2.7.6 → 2.7.10
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/workflows/ci.yml +2 -2
- package/README.md +14 -11
- package/bench.js +28 -0
- package/index.d.ts +1 -0
- package/index.js +26 -39
- package/package.json +3 -2
- package/test/oneof.test.js +102 -0
- package/test/types/test.ts +8 -0
- package/test/webpack.test.js +50 -0
package/.github/workflows/ci.yml
CHANGED
|
@@ -22,7 +22,7 @@ jobs:
|
|
|
22
22
|
- uses: actions/checkout@v2.3.4
|
|
23
23
|
|
|
24
24
|
- name: Use Node.js
|
|
25
|
-
uses: actions/setup-node@v2.
|
|
25
|
+
uses: actions/setup-node@v2.4.0
|
|
26
26
|
with:
|
|
27
27
|
node-version: ${{ matrix.node-version }}
|
|
28
28
|
|
|
@@ -38,6 +38,6 @@ jobs:
|
|
|
38
38
|
needs: test
|
|
39
39
|
runs-on: ubuntu-latest
|
|
40
40
|
steps:
|
|
41
|
-
- uses: fastify/github-action-merge-dependabot@v2.
|
|
41
|
+
- uses: fastify/github-action-merge-dependabot@v2.4.0
|
|
42
42
|
with:
|
|
43
43
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
package/README.md
CHANGED
|
@@ -12,22 +12,25 @@ __fast-json-stringify__ is significantly faster than `JSON.stringify()` for smal
|
|
|
12
12
|
##### Benchmarks
|
|
13
13
|
|
|
14
14
|
- Machine: `EX41S-SSD, Intel Core i7, 4Ghz, 64GB RAM, 4C/8T, SSD`.
|
|
15
|
-
- Node.js `
|
|
15
|
+
- Node.js `v16.9.1`
|
|
16
16
|
|
|
17
17
|
```
|
|
18
|
-
FJS creation x
|
|
18
|
+
FJS creation x 6,040 ops/sec ±1.17% (91 runs sampled)
|
|
19
19
|
|
|
20
|
-
JSON.stringify array x 5,
|
|
21
|
-
fast-json-stringify array x
|
|
20
|
+
JSON.stringify array x 5,519 ops/sec ±0.08% (99 runs sampled)
|
|
21
|
+
fast-json-stringify array x 7,143 ops/sec ±0.14% (97 runs sampled)
|
|
22
22
|
|
|
23
|
-
JSON.stringify long string x
|
|
24
|
-
fast-json-stringify long string x
|
|
23
|
+
JSON.stringify long string x 16,438 ops/sec ±0.32% (98 runs sampled)
|
|
24
|
+
fast-json-stringify long string x 16,457 ops/sec ±0.09% (97 runs sampled)
|
|
25
25
|
|
|
26
|
-
JSON.stringify short string x
|
|
27
|
-
fast-json-stringify short string x
|
|
26
|
+
JSON.stringify short string x 12,061,258 ops/sec ±0.32% (97 runs sampled)
|
|
27
|
+
fast-json-stringify short string x 35,531,071 ops/sec ±0.17% (94 runs sampled)
|
|
28
28
|
|
|
29
|
-
JSON.stringify obj x 3,
|
|
30
|
-
fast-json-stringify obj x
|
|
29
|
+
JSON.stringify obj x 3,079,746 ops/sec ±0.09% (95 runs sampled)
|
|
30
|
+
fast-json-stringify obj x 7,721,569 ops/sec ±0.12% (98 runs sampled)
|
|
31
|
+
|
|
32
|
+
JSON stringify date x 1,149,786 ops/sec ±0.10% (99 runs sampled)
|
|
33
|
+
fast-json-stringify date format x 1,674,498 ops/sec ±0.12% (99 runs sampled)
|
|
31
34
|
```
|
|
32
35
|
|
|
33
36
|
#### Table of contents:
|
|
@@ -342,7 +345,7 @@ const stringify = fastJson({
|
|
|
342
345
|
savedId: { type: 'string' }
|
|
343
346
|
},
|
|
344
347
|
// without "required" validation any object will match
|
|
345
|
-
required: ['
|
|
348
|
+
required: ['savedId']
|
|
346
349
|
},
|
|
347
350
|
{
|
|
348
351
|
type: 'object',
|
package/bench.js
CHANGED
|
@@ -50,22 +50,38 @@ const arraySchemaCJS = {
|
|
|
50
50
|
items: schemaCJS
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
const dateFormatSchema = {
|
|
54
|
+
description: 'Date of birth',
|
|
55
|
+
type: 'string',
|
|
56
|
+
format: 'date'
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const dateFormatSchemaCJS = {
|
|
60
|
+
description: 'Date of birth',
|
|
61
|
+
type: 'string',
|
|
62
|
+
format: 'date'
|
|
63
|
+
}
|
|
64
|
+
|
|
53
65
|
const obj = {
|
|
54
66
|
firstName: 'Matteo',
|
|
55
67
|
lastName: 'Collina',
|
|
56
68
|
age: 32
|
|
57
69
|
}
|
|
58
70
|
|
|
71
|
+
const date = new Date()
|
|
72
|
+
|
|
59
73
|
const multiArray = []
|
|
60
74
|
|
|
61
75
|
const CJS = require('compile-json-stringify')
|
|
62
76
|
const CJSStringify = CJS(schemaCJS)
|
|
63
77
|
const CJSStringifyArray = CJS(arraySchemaCJS)
|
|
78
|
+
const CJSStringifyDate = CJS(dateFormatSchemaCJS)
|
|
64
79
|
const CJSStringifyString = CJS({ type: 'string' })
|
|
65
80
|
|
|
66
81
|
const FJS = require('.')
|
|
67
82
|
const stringify = FJS(schema)
|
|
68
83
|
const stringifyArray = FJS(arraySchema)
|
|
84
|
+
const stringifyDate = FJS(dateFormatSchema)
|
|
69
85
|
const stringifyString = FJS({ type: 'string' })
|
|
70
86
|
let str = ''
|
|
71
87
|
|
|
@@ -138,6 +154,18 @@ suite.add('compile-json-stringify obj', function () {
|
|
|
138
154
|
CJSStringify(obj)
|
|
139
155
|
})
|
|
140
156
|
|
|
157
|
+
suite.add('JSON stringify date', function () {
|
|
158
|
+
JSON.stringify(date)
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
suite.add('fast-json-stringify date format', function () {
|
|
162
|
+
stringifyDate(date)
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
suite.add('compile-json-stringify date format', function () {
|
|
166
|
+
CJSStringifyDate(date)
|
|
167
|
+
})
|
|
168
|
+
|
|
141
169
|
suite.on('cycle', cycle)
|
|
142
170
|
|
|
143
171
|
suite.run()
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -72,21 +72,7 @@ function build (schema, options) {
|
|
|
72
72
|
`
|
|
73
73
|
|
|
74
74
|
code += `
|
|
75
|
-
${
|
|
76
|
-
${$asAny.toString()}
|
|
77
|
-
${$asString.toString()}
|
|
78
|
-
${$asStringNullable.toString()}
|
|
79
|
-
${$asStringSmall.toString()}
|
|
80
|
-
${$asDatetime.toString()}
|
|
81
|
-
${$asDate.toString()}
|
|
82
|
-
${$asTime.toString()}
|
|
83
|
-
${$asNumber.toString()}
|
|
84
|
-
${$asNumberNullable.toString()}
|
|
85
|
-
${$asInteger.toString()}
|
|
86
|
-
${$asIntegerNullable.toString()}
|
|
87
|
-
${$asNull.toString()}
|
|
88
|
-
${$asBoolean.toString()}
|
|
89
|
-
${$asBooleanNullable.toString()}
|
|
75
|
+
${asFunctions}
|
|
90
76
|
|
|
91
77
|
var isLong = ${isLong ? isLong.toString() : false}
|
|
92
78
|
|
|
@@ -116,19 +102,19 @@ function build (schema, options) {
|
|
|
116
102
|
code = buildObject(location, code, main)
|
|
117
103
|
break
|
|
118
104
|
case 'string':
|
|
119
|
-
main = schema.nullable ? $asStringNullable
|
|
105
|
+
main = schema.nullable ? '$asStringNullable' : getStringSerializer(schema.format)
|
|
120
106
|
break
|
|
121
107
|
case 'integer':
|
|
122
|
-
main = schema.nullable ? $asIntegerNullable
|
|
108
|
+
main = schema.nullable ? '$asIntegerNullable' : '$asInteger'
|
|
123
109
|
break
|
|
124
110
|
case 'number':
|
|
125
|
-
main = schema.nullable ? $asNumberNullable
|
|
111
|
+
main = schema.nullable ? '$asNumberNullable' : '$asNumber'
|
|
126
112
|
break
|
|
127
113
|
case 'boolean':
|
|
128
|
-
main = schema.nullable ? $asBooleanNullable
|
|
114
|
+
main = schema.nullable ? '$asBooleanNullable' : '$asBoolean'
|
|
129
115
|
break
|
|
130
116
|
case 'null':
|
|
131
|
-
main = $asNull
|
|
117
|
+
main = '$asNull'
|
|
132
118
|
break
|
|
133
119
|
case 'array':
|
|
134
120
|
main = '$main'
|
|
@@ -233,6 +219,7 @@ function getTestSerializer (format) {
|
|
|
233
219
|
return stringSerializerMap[format]
|
|
234
220
|
}
|
|
235
221
|
|
|
222
|
+
const asFunctions = `
|
|
236
223
|
function $pad2Zeros (num) {
|
|
237
224
|
const s = '00' + num
|
|
238
225
|
return s[s.length - 2] + s[s.length - 1]
|
|
@@ -298,10 +285,7 @@ function $asDatetime (date, skipQuotes) {
|
|
|
298
285
|
function $asDate (date, skipQuotes) {
|
|
299
286
|
const quotes = skipQuotes === true ? '' : '"'
|
|
300
287
|
if (date instanceof Date) {
|
|
301
|
-
|
|
302
|
-
const month = new Intl.DateTimeFormat('en', { month: '2-digit' }).format(date)
|
|
303
|
-
const day = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(date)
|
|
304
|
-
return quotes + year + '-' + month + '-' + day + quotes
|
|
288
|
+
return quotes + new Date(date.getTime() - (date.getTimezoneOffset() * 60000 )).toISOString().slice(0, 10) + quotes
|
|
305
289
|
} else if (date && typeof date.format === 'function') {
|
|
306
290
|
return quotes + date.format('YYYY-MM-DD') + quotes
|
|
307
291
|
} else {
|
|
@@ -372,7 +356,7 @@ function $asStringSmall (str) {
|
|
|
372
356
|
surrogateFound = true
|
|
373
357
|
}
|
|
374
358
|
if (point === 34 || point === 92) {
|
|
375
|
-
result += str.slice(last, i) + '
|
|
359
|
+
result += str.slice(last, i) + '\\\\'
|
|
376
360
|
last = i
|
|
377
361
|
found = true
|
|
378
362
|
}
|
|
@@ -385,6 +369,7 @@ function $asStringSmall (str) {
|
|
|
385
369
|
}
|
|
386
370
|
return ((point < 32) || (surrogateFound === true)) ? JSON.stringify(str) : '"' + result + '"'
|
|
387
371
|
}
|
|
372
|
+
`
|
|
388
373
|
|
|
389
374
|
function addPatternProperties (location) {
|
|
390
375
|
const schema = location.schema
|
|
@@ -928,7 +913,7 @@ function buildObject (location, code, name) {
|
|
|
928
913
|
if (schema.nullable) {
|
|
929
914
|
code += `
|
|
930
915
|
if(input === null) {
|
|
931
|
-
return '
|
|
916
|
+
return 'null';
|
|
932
917
|
}
|
|
933
918
|
`
|
|
934
919
|
}
|
|
@@ -967,13 +952,10 @@ function buildArray (location, code, name, key = null) {
|
|
|
967
952
|
if (schema.nullable) {
|
|
968
953
|
code += `
|
|
969
954
|
if(obj === null) {
|
|
970
|
-
return '
|
|
955
|
+
return 'null';
|
|
971
956
|
}
|
|
972
957
|
`
|
|
973
958
|
}
|
|
974
|
-
code += `
|
|
975
|
-
var json = '['
|
|
976
|
-
`
|
|
977
959
|
const laterCode = ''
|
|
978
960
|
|
|
979
961
|
// default to any items type
|
|
@@ -1035,15 +1017,17 @@ function buildArray (location, code, name, key = null) {
|
|
|
1035
1017
|
|
|
1036
1018
|
code += `
|
|
1037
1019
|
var l = obj.length
|
|
1038
|
-
var
|
|
1020
|
+
var jsonOutput= ''
|
|
1039
1021
|
for (var i = 0; i < l; i++) {
|
|
1040
|
-
|
|
1041
|
-
json += ','
|
|
1042
|
-
}
|
|
1022
|
+
var json = ''
|
|
1043
1023
|
${result.code}
|
|
1024
|
+
jsonOutput += json
|
|
1025
|
+
|
|
1026
|
+
if (json.length > 0 && i < l - 1) {
|
|
1027
|
+
jsonOutput += ','
|
|
1028
|
+
}
|
|
1044
1029
|
}
|
|
1045
|
-
|
|
1046
|
-
return json
|
|
1030
|
+
return \`[\${jsonOutput}]\`
|
|
1047
1031
|
}
|
|
1048
1032
|
${result.laterCode}
|
|
1049
1033
|
`
|
|
@@ -1226,9 +1210,12 @@ function nested (laterCode, name, key, location, subKey, isArray) {
|
|
|
1226
1210
|
`
|
|
1227
1211
|
laterCode = nestedResult.laterCode
|
|
1228
1212
|
})
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1213
|
+
|
|
1214
|
+
if (!isArray) {
|
|
1215
|
+
code += `
|
|
1216
|
+
else json+= null
|
|
1217
|
+
`
|
|
1218
|
+
}
|
|
1232
1219
|
} else if (isEmpty(schema)) {
|
|
1233
1220
|
code += `
|
|
1234
1221
|
json += JSON.stringify(obj${accessor})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fast-json-stringify",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.10",
|
|
4
4
|
"description": "Stringify your JSON at max speed",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -41,7 +41,8 @@
|
|
|
41
41
|
"semver": "^7.1.0",
|
|
42
42
|
"standard": "^16.0.1",
|
|
43
43
|
"tap": "^15.0.0",
|
|
44
|
-
"typescript": "^4.0.2"
|
|
44
|
+
"typescript": "^4.0.2",
|
|
45
|
+
"webpack": "^5.40.0"
|
|
45
46
|
},
|
|
46
47
|
"dependencies": {
|
|
47
48
|
"ajv": "^6.11.0",
|
package/test/oneof.test.js
CHANGED
|
@@ -401,3 +401,105 @@ test('oneOf object with field of type string with format or null', (t) => {
|
|
|
401
401
|
prop: toStringify
|
|
402
402
|
}), `{"prop":"${toStringify.toISOString()}"}`)
|
|
403
403
|
})
|
|
404
|
+
|
|
405
|
+
test('one array item match oneOf types', (t) => {
|
|
406
|
+
t.plan(1)
|
|
407
|
+
|
|
408
|
+
const schema = {
|
|
409
|
+
type: 'object',
|
|
410
|
+
additionalProperties: false,
|
|
411
|
+
required: ['data'],
|
|
412
|
+
properties: {
|
|
413
|
+
data: {
|
|
414
|
+
type: 'array',
|
|
415
|
+
minItems: 1,
|
|
416
|
+
items: {
|
|
417
|
+
oneOf: [
|
|
418
|
+
{
|
|
419
|
+
type: 'string'
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
type: 'number'
|
|
423
|
+
}
|
|
424
|
+
]
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const stringify = build(schema)
|
|
431
|
+
|
|
432
|
+
const responseWithMappedType = stringify({
|
|
433
|
+
data: [false, 'foo']
|
|
434
|
+
})
|
|
435
|
+
|
|
436
|
+
t.equal('{"data":["foo"]}', responseWithMappedType)
|
|
437
|
+
})
|
|
438
|
+
|
|
439
|
+
test('some array items match oneOf types', (t) => {
|
|
440
|
+
t.plan(1)
|
|
441
|
+
|
|
442
|
+
const schema = {
|
|
443
|
+
type: 'object',
|
|
444
|
+
additionalProperties: false,
|
|
445
|
+
required: ['data'],
|
|
446
|
+
properties: {
|
|
447
|
+
data: {
|
|
448
|
+
type: 'array',
|
|
449
|
+
minItems: 1,
|
|
450
|
+
items: {
|
|
451
|
+
oneOf: [
|
|
452
|
+
{
|
|
453
|
+
type: 'string'
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
type: 'number'
|
|
457
|
+
}
|
|
458
|
+
]
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const stringify = build(schema)
|
|
465
|
+
|
|
466
|
+
const responseWithMappedTypes = stringify({
|
|
467
|
+
data: [false, 'foo', true, 5]
|
|
468
|
+
})
|
|
469
|
+
|
|
470
|
+
t.equal('{"data":["foo",5]}', responseWithMappedTypes)
|
|
471
|
+
})
|
|
472
|
+
|
|
473
|
+
test('all array items does not match oneOf types', (t) => {
|
|
474
|
+
t.plan(1)
|
|
475
|
+
|
|
476
|
+
const schema = {
|
|
477
|
+
type: 'object',
|
|
478
|
+
additionalProperties: false,
|
|
479
|
+
required: ['data'],
|
|
480
|
+
properties: {
|
|
481
|
+
data: {
|
|
482
|
+
type: 'array',
|
|
483
|
+
minItems: 1,
|
|
484
|
+
items: {
|
|
485
|
+
oneOf: [
|
|
486
|
+
{
|
|
487
|
+
type: 'string'
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
type: 'number'
|
|
491
|
+
}
|
|
492
|
+
]
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
const stringify = build(schema)
|
|
499
|
+
|
|
500
|
+
const emptyResponse = stringify({
|
|
501
|
+
data: [null, false, true, undefined, [], {}]
|
|
502
|
+
})
|
|
503
|
+
|
|
504
|
+
t.equal('{"data":[]}', emptyResponse)
|
|
505
|
+
})
|
package/test/types/test.ts
CHANGED
|
@@ -135,3 +135,11 @@ const schema11: Schema = {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
build(schema11)({ something: 'a string', somethingElse: 42 })
|
|
138
|
+
|
|
139
|
+
// String schema with format
|
|
140
|
+
const schema12: Schema = {
|
|
141
|
+
type: 'string',
|
|
142
|
+
format: 'date-time'
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
build(schema12)(new Date())
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const test = require('tap').test
|
|
4
|
+
const webpack = require('webpack')
|
|
5
|
+
const path = require('path')
|
|
6
|
+
|
|
7
|
+
test('the library should work with webpack', async (t) => {
|
|
8
|
+
t.plan(1)
|
|
9
|
+
const targetdir = path.resolve(__dirname, '..', '.cache')
|
|
10
|
+
const targetname = path.join(targetdir, 'webpacktest.js')
|
|
11
|
+
const wopts = {
|
|
12
|
+
entry: path.resolve(__dirname, '..', 'index.js'),
|
|
13
|
+
mode: 'production',
|
|
14
|
+
target: 'node',
|
|
15
|
+
output: {
|
|
16
|
+
path: targetdir,
|
|
17
|
+
filename: 'webpacktest.js',
|
|
18
|
+
library: {
|
|
19
|
+
name: 'fastJsonStringify',
|
|
20
|
+
type: 'umd'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
await new Promise((resolve, reject) => {
|
|
25
|
+
webpack(wopts, (err, stats) => {
|
|
26
|
+
if (err) { reject(err) } else { resolve(stats) };
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
const build = require(targetname)
|
|
30
|
+
const stringify = build({
|
|
31
|
+
title: 'webpack should not rename code to be executed',
|
|
32
|
+
type: 'object',
|
|
33
|
+
properties: {
|
|
34
|
+
foo: {
|
|
35
|
+
type: 'string'
|
|
36
|
+
},
|
|
37
|
+
bar: {
|
|
38
|
+
type: 'boolean'
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
patternProperties: {
|
|
42
|
+
foo: {
|
|
43
|
+
type: 'number'
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
const obj = { foo: '42', bar: true }
|
|
49
|
+
t.equal(stringify(obj), '{"foo":"42","bar":true}')
|
|
50
|
+
})
|