fast-json-stringify 2.7.3 → 2.7.7
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 +3 -1
- package/index.js +25 -32
- package/package.json +3 -2
- package/test/anyof.test.js +47 -1
- package/test/date.test.js +1 -1
- package/test/integer.test.js +43 -0
- package/test/webpack.test.js +50 -0
package/.github/workflows/ci.yml
CHANGED
|
@@ -19,7 +19,7 @@ jobs:
|
|
|
19
19
|
os: [macos-latest, ubuntu-latest, windows-latest]
|
|
20
20
|
|
|
21
21
|
steps:
|
|
22
|
-
- uses: actions/checkout@v2
|
|
22
|
+
- uses: actions/checkout@v2.3.4
|
|
23
23
|
|
|
24
24
|
- name: Use Node.js
|
|
25
25
|
uses: actions/setup-node@v2.1.5
|
|
@@ -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.1.1
|
|
42
42
|
with:
|
|
43
43
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
package/README.md
CHANGED
|
@@ -139,6 +139,8 @@ And nested ones, too.
|
|
|
139
139
|
| `date` | `2020-04-03` |
|
|
140
140
|
| `time` | `09:11:08` |
|
|
141
141
|
|
|
142
|
+
**Note**: In the case of string formatted Date and not Date Object, there will be no manipulation on it. It should be properly formatted.
|
|
143
|
+
|
|
142
144
|
Example with a MomentJS object:
|
|
143
145
|
|
|
144
146
|
```javascript
|
|
@@ -340,7 +342,7 @@ const stringify = fastJson({
|
|
|
340
342
|
savedId: { type: 'string' }
|
|
341
343
|
},
|
|
342
344
|
// without "required" validation any object will match
|
|
343
|
-
required: ['
|
|
345
|
+
required: ['savedId']
|
|
344
346
|
},
|
|
345
347
|
{
|
|
346
348
|
type: 'object',
|
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
|
|
|
@@ -292,7 +278,7 @@ function $asDatetime (date, skipQuotes) {
|
|
|
292
278
|
} else if (date && typeof date.toISOString === 'function') {
|
|
293
279
|
return quotes + date.toISOString() + quotes
|
|
294
280
|
} else {
|
|
295
|
-
return $asString(date)
|
|
281
|
+
return $asString(date, skipQuotes)
|
|
296
282
|
}
|
|
297
283
|
}
|
|
298
284
|
|
|
@@ -306,7 +292,7 @@ function $asDate (date, skipQuotes) {
|
|
|
306
292
|
} else if (date && typeof date.format === 'function') {
|
|
307
293
|
return quotes + date.format('YYYY-MM-DD') + quotes
|
|
308
294
|
} else {
|
|
309
|
-
return $asString(date)
|
|
295
|
+
return $asString(date, skipQuotes)
|
|
310
296
|
}
|
|
311
297
|
}
|
|
312
298
|
|
|
@@ -320,20 +306,26 @@ function $asTime (date, skipQuotes) {
|
|
|
320
306
|
} else if (date && typeof date.format === 'function') {
|
|
321
307
|
return quotes + date.format('HH:mm:ss') + quotes
|
|
322
308
|
} else {
|
|
323
|
-
return $asString(date)
|
|
309
|
+
return $asString(date, skipQuotes)
|
|
324
310
|
}
|
|
325
311
|
}
|
|
326
312
|
|
|
327
|
-
function $asString (str) {
|
|
313
|
+
function $asString (str, skipQuotes) {
|
|
314
|
+
const quotes = skipQuotes === true ? '' : '"'
|
|
328
315
|
if (str instanceof Date) {
|
|
329
|
-
return
|
|
316
|
+
return quotes + str.toISOString() + quotes
|
|
330
317
|
} else if (str === null) {
|
|
331
|
-
return
|
|
318
|
+
return quotes + quotes
|
|
332
319
|
} else if (str instanceof RegExp) {
|
|
333
320
|
str = str.source
|
|
334
321
|
} else if (typeof str !== 'string') {
|
|
335
322
|
str = str.toString()
|
|
336
323
|
}
|
|
324
|
+
// If we skipQuotes it means that we are using it as test
|
|
325
|
+
// no need to test the string length for the render
|
|
326
|
+
if (skipQuotes) {
|
|
327
|
+
return str
|
|
328
|
+
}
|
|
337
329
|
|
|
338
330
|
if (str.length < 42) {
|
|
339
331
|
return $asStringSmall(str)
|
|
@@ -367,7 +359,7 @@ function $asStringSmall (str) {
|
|
|
367
359
|
surrogateFound = true
|
|
368
360
|
}
|
|
369
361
|
if (point === 34 || point === 92) {
|
|
370
|
-
result += str.slice(last, i) + '
|
|
362
|
+
result += str.slice(last, i) + '\\\\'
|
|
371
363
|
last = i
|
|
372
364
|
found = true
|
|
373
365
|
}
|
|
@@ -380,6 +372,7 @@ function $asStringSmall (str) {
|
|
|
380
372
|
}
|
|
381
373
|
return ((point < 32) || (surrogateFound === true)) ? JSON.stringify(str) : '"' + result + '"'
|
|
382
374
|
}
|
|
375
|
+
`
|
|
383
376
|
|
|
384
377
|
function addPatternProperties (location) {
|
|
385
378
|
const schema = location.schema
|
|
@@ -746,7 +739,7 @@ function buildCode (location, code, laterCode, name) {
|
|
|
746
739
|
`
|
|
747
740
|
} else {
|
|
748
741
|
code += `
|
|
749
|
-
var t =
|
|
742
|
+
var t = $asInteger(obj[${sanitized}])
|
|
750
743
|
if (!isNaN(t)) {
|
|
751
744
|
${addComma}
|
|
752
745
|
json += ${asString} + ':' + t
|
|
@@ -923,7 +916,7 @@ function buildObject (location, code, name) {
|
|
|
923
916
|
if (schema.nullable) {
|
|
924
917
|
code += `
|
|
925
918
|
if(input === null) {
|
|
926
|
-
return '
|
|
919
|
+
return 'null';
|
|
927
920
|
}
|
|
928
921
|
`
|
|
929
922
|
}
|
|
@@ -962,7 +955,7 @@ function buildArray (location, code, name, key = null) {
|
|
|
962
955
|
if (schema.nullable) {
|
|
963
956
|
code += `
|
|
964
957
|
if(obj === null) {
|
|
965
|
-
return '
|
|
958
|
+
return 'null';
|
|
966
959
|
}
|
|
967
960
|
`
|
|
968
961
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fast-json-stringify",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.7",
|
|
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/anyof.test.js
CHANGED
|
@@ -448,7 +448,7 @@ test('anyOf with enum with more than 100 entries', (t) => {
|
|
|
448
448
|
t.equal(value, '["EUR","USD",null]')
|
|
449
449
|
})
|
|
450
450
|
|
|
451
|
-
test('anyOf object with field of type string with format or null', (t) => {
|
|
451
|
+
test('anyOf object with field date-time of type string with format or null', (t) => {
|
|
452
452
|
t.plan(1)
|
|
453
453
|
const toStringify = new Date()
|
|
454
454
|
const withOneOfSchema = {
|
|
@@ -471,3 +471,49 @@ test('anyOf object with field of type string with format or null', (t) => {
|
|
|
471
471
|
prop: toStringify
|
|
472
472
|
}), `{"prop":"${toStringify.toISOString()}"}`)
|
|
473
473
|
})
|
|
474
|
+
|
|
475
|
+
test('anyOf object with field date of type string with format or null', (t) => {
|
|
476
|
+
t.plan(1)
|
|
477
|
+
const toStringify = '2011-01-01'
|
|
478
|
+
const withOneOfSchema = {
|
|
479
|
+
type: 'object',
|
|
480
|
+
properties: {
|
|
481
|
+
prop: {
|
|
482
|
+
anyOf: [{
|
|
483
|
+
type: 'string',
|
|
484
|
+
format: 'date'
|
|
485
|
+
}, {
|
|
486
|
+
type: 'null'
|
|
487
|
+
}]
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
const withOneOfStringify = build(withOneOfSchema)
|
|
493
|
+
t.equal(withOneOfStringify({
|
|
494
|
+
prop: toStringify
|
|
495
|
+
}), '{"prop":"2011-01-01"}')
|
|
496
|
+
})
|
|
497
|
+
|
|
498
|
+
test('anyOf object with invalid field date of type string with format or null', (t) => {
|
|
499
|
+
t.plan(1)
|
|
500
|
+
const toStringify = 'foo bar'
|
|
501
|
+
const withOneOfSchema = {
|
|
502
|
+
type: 'object',
|
|
503
|
+
properties: {
|
|
504
|
+
prop: {
|
|
505
|
+
anyOf: [{
|
|
506
|
+
type: 'string',
|
|
507
|
+
format: 'date'
|
|
508
|
+
}, {
|
|
509
|
+
type: 'null'
|
|
510
|
+
}]
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
const withOneOfStringify = build(withOneOfSchema)
|
|
516
|
+
t.equal(withOneOfStringify({
|
|
517
|
+
prop: toStringify
|
|
518
|
+
}), '{"prop":null}')
|
|
519
|
+
})
|
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' },
|
|
@@ -137,3 +142,41 @@ if (semver.gt(process.versions.node, '10.3.0')) {
|
|
|
137
142
|
t.pass('Skip because Node version < 10.4')
|
|
138
143
|
t.end()
|
|
139
144
|
}
|
|
145
|
+
|
|
146
|
+
test('should round integer object parameter', t => {
|
|
147
|
+
t.plan(2)
|
|
148
|
+
|
|
149
|
+
const schema = { type: 'object', properties: { magic: { type: 'integer' } } }
|
|
150
|
+
const validate = validator(schema)
|
|
151
|
+
const stringify = build(schema, { rounding: 'ceil' })
|
|
152
|
+
const output = stringify({ magic: 4.2 })
|
|
153
|
+
|
|
154
|
+
t.equal(output, '{"magic":5}')
|
|
155
|
+
t.ok(validate(JSON.parse(output)), 'valid schema')
|
|
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
|
+
})
|
|
@@ -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
|
+
})
|