fast-json-stringify 2.7.5 → 2.7.9
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 +1 -1
- package/index.d.ts +1 -0
- package/index.js +22 -30
- package/package.json +3 -2
- package/test/date.test.js +1 -1
- package/test/integer.test.js +32 -1
- 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
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]
|
|
@@ -254,9 +241,8 @@ function $asInteger (i) {
|
|
|
254
241
|
} else if (Number.isInteger(i)) {
|
|
255
242
|
return $asNumber(i)
|
|
256
243
|
} else {
|
|
257
|
-
// if the output is NaN the type is coerced to int 0
|
|
258
244
|
/* eslint no-undef: "off" */
|
|
259
|
-
return $asNumber(parseInteger(i)
|
|
245
|
+
return $asNumber(parseInteger(i))
|
|
260
246
|
}
|
|
261
247
|
}
|
|
262
248
|
|
|
@@ -373,7 +359,7 @@ function $asStringSmall (str) {
|
|
|
373
359
|
surrogateFound = true
|
|
374
360
|
}
|
|
375
361
|
if (point === 34 || point === 92) {
|
|
376
|
-
result += str.slice(last, i) + '
|
|
362
|
+
result += str.slice(last, i) + '\\\\'
|
|
377
363
|
last = i
|
|
378
364
|
found = true
|
|
379
365
|
}
|
|
@@ -386,6 +372,7 @@ function $asStringSmall (str) {
|
|
|
386
372
|
}
|
|
387
373
|
return ((point < 32) || (surrogateFound === true)) ? JSON.stringify(str) : '"' + result + '"'
|
|
388
374
|
}
|
|
375
|
+
`
|
|
389
376
|
|
|
390
377
|
function addPatternProperties (location) {
|
|
391
378
|
const schema = location.schema
|
|
@@ -929,7 +916,7 @@ function buildObject (location, code, name) {
|
|
|
929
916
|
if (schema.nullable) {
|
|
930
917
|
code += `
|
|
931
918
|
if(input === null) {
|
|
932
|
-
return '
|
|
919
|
+
return 'null';
|
|
933
920
|
}
|
|
934
921
|
`
|
|
935
922
|
}
|
|
@@ -968,7 +955,7 @@ function buildArray (location, code, name, key = null) {
|
|
|
968
955
|
if (schema.nullable) {
|
|
969
956
|
code += `
|
|
970
957
|
if(obj === null) {
|
|
971
|
-
return '
|
|
958
|
+
return 'null';
|
|
972
959
|
}
|
|
973
960
|
`
|
|
974
961
|
}
|
|
@@ -1036,9 +1023,11 @@ function buildArray (location, code, name, key = null) {
|
|
|
1036
1023
|
|
|
1037
1024
|
code += `
|
|
1038
1025
|
var l = obj.length
|
|
1039
|
-
|
|
1026
|
+
|
|
1040
1027
|
for (var i = 0; i < l; i++) {
|
|
1041
|
-
|
|
1028
|
+
var jsonLastChar = json[json.length - 1]
|
|
1029
|
+
|
|
1030
|
+
if (i > 0 && jsonLastChar !== '[' && jsonLastChar !== ',') {
|
|
1042
1031
|
json += ','
|
|
1043
1032
|
}
|
|
1044
1033
|
${result.code}
|
|
@@ -1227,9 +1216,12 @@ function nested (laterCode, name, key, location, subKey, isArray) {
|
|
|
1227
1216
|
`
|
|
1228
1217
|
laterCode = nestedResult.laterCode
|
|
1229
1218
|
})
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1219
|
+
|
|
1220
|
+
if (!isArray) {
|
|
1221
|
+
code += `
|
|
1222
|
+
else json+= null
|
|
1223
|
+
`
|
|
1224
|
+
}
|
|
1233
1225
|
} else if (isEmpty(schema)) {
|
|
1234
1226
|
code += `
|
|
1235
1227
|
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.9",
|
|
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/date.test.js
CHANGED
|
@@ -76,7 +76,7 @@ test('verify padding for rendered date in a string when format is date', (t) =>
|
|
|
76
76
|
t.ok(validate(JSON.parse(output)), 'valid schema')
|
|
77
77
|
})
|
|
78
78
|
|
|
79
|
-
test('render a date in a string when format is time as
|
|
79
|
+
test('render a date in a string when format is time as kk:mm:ss', (t) => {
|
|
80
80
|
t.plan(3)
|
|
81
81
|
|
|
82
82
|
const schema = {
|
package/test/integer.test.js
CHANGED
|
@@ -6,6 +6,7 @@ const semver = require('semver')
|
|
|
6
6
|
const validator = require('is-my-json-valid')
|
|
7
7
|
const proxyquire = require('proxyquire')
|
|
8
8
|
const build = proxyquire('..', { long: null })
|
|
9
|
+
const ROUNDING_TYPES = ['ceil', 'floor', 'round']
|
|
9
10
|
|
|
10
11
|
test('render an integer as JSON', (t) => {
|
|
11
12
|
t.plan(2)
|
|
@@ -40,6 +41,10 @@ test('render a float as an integer', (t) => {
|
|
|
40
41
|
const cases = [
|
|
41
42
|
{ input: Math.PI, output: '3' },
|
|
42
43
|
{ input: 5.0, output: '5' },
|
|
44
|
+
{ input: null, output: '0' },
|
|
45
|
+
{ input: 0, output: '0' },
|
|
46
|
+
{ input: 0.0, output: '0' },
|
|
47
|
+
{ input: 42, output: '42' },
|
|
43
48
|
{ input: 1.99999, output: '1' },
|
|
44
49
|
{ input: -45.05, output: '-45' },
|
|
45
50
|
{ input: 0.95, output: '1', rounding: 'ceil' },
|
|
@@ -138,7 +143,7 @@ if (semver.gt(process.versions.node, '10.3.0')) {
|
|
|
138
143
|
t.end()
|
|
139
144
|
}
|
|
140
145
|
|
|
141
|
-
test('should round
|
|
146
|
+
test('should round integer object parameter', t => {
|
|
142
147
|
t.plan(2)
|
|
143
148
|
|
|
144
149
|
const schema = { type: 'object', properties: { magic: { type: 'integer' } } }
|
|
@@ -149,3 +154,29 @@ test('should round interger object parameter ', t => {
|
|
|
149
154
|
t.equal(output, '{"magic":5}')
|
|
150
155
|
t.ok(validate(JSON.parse(output)), 'valid schema')
|
|
151
156
|
})
|
|
157
|
+
|
|
158
|
+
test('should not stringify a property if it does not exist', t => {
|
|
159
|
+
t.plan(2)
|
|
160
|
+
|
|
161
|
+
const schema = { title: 'Example Schema', type: 'object', properties: { age: { type: 'integer' } } }
|
|
162
|
+
const validate = validator(schema)
|
|
163
|
+
const stringify = build(schema)
|
|
164
|
+
const output = stringify({})
|
|
165
|
+
|
|
166
|
+
t.equal(output, '{}')
|
|
167
|
+
t.ok(validate(JSON.parse(output)), 'valid schema')
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
ROUNDING_TYPES.forEach((rounding) => {
|
|
171
|
+
test(`should not stringify a property if it does not exist (rounding: ${rounding})`, t => {
|
|
172
|
+
t.plan(2)
|
|
173
|
+
|
|
174
|
+
const schema = { type: 'object', properties: { magic: { type: 'integer' } } }
|
|
175
|
+
const validate = validator(schema)
|
|
176
|
+
const stringify = build(schema, { rounding })
|
|
177
|
+
const output = stringify({})
|
|
178
|
+
|
|
179
|
+
t.equal(output, '{}')
|
|
180
|
+
t.ok(validate(JSON.parse(output)), 'valid schema')
|
|
181
|
+
})
|
|
182
|
+
})
|
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
|
+
})
|