fast-json-stringify 5.9.1 → 5.10.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/README.md +2 -0
- package/index.js +19 -6
- package/package.json +6 -3
- package/test/array.test.js +25 -1
- package/test/toJSON.test.js +33 -4
- package/test/typesArray.test.js +3 -2
package/README.md
CHANGED
|
@@ -590,6 +590,8 @@ Otherwise, instead of raising an error, null values will be coerced as follows:
|
|
|
590
590
|
- `number` -> `0`
|
|
591
591
|
- `string` -> `""`
|
|
592
592
|
- `boolean` -> `false`
|
|
593
|
+
- `object` -> `{}`
|
|
594
|
+
- `array` -> `[]`
|
|
593
595
|
|
|
594
596
|
<a name="largearrays"></a>
|
|
595
597
|
#### Large Arrays
|
package/index.js
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
const merge = require('@fastify/deepmerge')()
|
|
6
6
|
const clone = require('rfdc')({ proto: true })
|
|
7
|
-
const { randomUUID } = require('crypto')
|
|
8
7
|
const { RefResolver } = require('json-schema-ref-resolver')
|
|
9
8
|
|
|
10
9
|
const validate = require('./lib/schema-validator')
|
|
@@ -31,6 +30,8 @@ const validLargeArrayMechanisms = [
|
|
|
31
30
|
|
|
32
31
|
const addComma = '!addComma && (addComma = true) || (json += \',\')'
|
|
33
32
|
|
|
33
|
+
let schemaIdCounter = 0
|
|
34
|
+
|
|
34
35
|
function isValidSchema (schema, name) {
|
|
35
36
|
if (!validate(schema)) {
|
|
36
37
|
if (name) {
|
|
@@ -86,7 +87,7 @@ function build (schema, options) {
|
|
|
86
87
|
options,
|
|
87
88
|
wrapObjects: true,
|
|
88
89
|
refResolver: new RefResolver(),
|
|
89
|
-
rootSchemaId: schema.$id ||
|
|
90
|
+
rootSchemaId: schema.$id || `__fjs_root_${schemaIdCounter++}`,
|
|
90
91
|
validatorSchemasIds: new Set()
|
|
91
92
|
}
|
|
92
93
|
|
|
@@ -500,7 +501,7 @@ function mergeAllOfSchema (context, location, schema, mergedSchema) {
|
|
|
500
501
|
}
|
|
501
502
|
delete mergedSchema.allOf
|
|
502
503
|
|
|
503
|
-
mergedSchema.$id = `
|
|
504
|
+
mergedSchema.$id = `__fjs_merged_${schemaIdCounter++}`
|
|
504
505
|
context.refResolver.addSchema(mergedSchema)
|
|
505
506
|
location.addMergedSchema(mergedSchema, mergedSchema.$id)
|
|
506
507
|
}
|
|
@@ -559,10 +560,13 @@ function buildObject (context, location) {
|
|
|
559
560
|
let functionCode = `
|
|
560
561
|
`
|
|
561
562
|
|
|
563
|
+
const nullable = schema.nullable === true
|
|
562
564
|
functionCode += `
|
|
563
565
|
// ${schemaRef}
|
|
564
566
|
function ${functionName} (input) {
|
|
565
567
|
const obj = ${toJSON('input')}
|
|
568
|
+
${!nullable ? 'if (obj === null) return \'{}\'' : ''}
|
|
569
|
+
|
|
566
570
|
${buildInnerObject(context, location)}
|
|
567
571
|
}
|
|
568
572
|
`
|
|
@@ -600,7 +604,9 @@ function buildArray (context, location) {
|
|
|
600
604
|
// ${schemaRef}
|
|
601
605
|
`
|
|
602
606
|
|
|
607
|
+
const nullable = schema.nullable === true
|
|
603
608
|
functionCode += `
|
|
609
|
+
${!nullable ? 'if (obj === null) return \'[]\'' : ''}
|
|
604
610
|
if (!Array.isArray(obj)) {
|
|
605
611
|
throw new TypeError(\`The value of '${schemaRef}' does not match schema definition.\`)
|
|
606
612
|
}
|
|
@@ -680,7 +686,15 @@ function buildArrayTypeCondition (type, accessor) {
|
|
|
680
686
|
condition = `obj${accessor} === null`
|
|
681
687
|
break
|
|
682
688
|
case 'string':
|
|
683
|
-
condition = `typeof obj${accessor} === 'string'
|
|
689
|
+
condition = `typeof obj${accessor} === 'string' ||
|
|
690
|
+
obj${accessor} === null ||
|
|
691
|
+
obj${accessor} instanceof Date ||
|
|
692
|
+
obj${accessor} instanceof RegExp ||
|
|
693
|
+
(
|
|
694
|
+
typeof obj${accessor} === "object" &&
|
|
695
|
+
typeof obj${accessor}.toString === "function" &&
|
|
696
|
+
obj${accessor}.toString !== Object.prototype.toString
|
|
697
|
+
)`
|
|
684
698
|
break
|
|
685
699
|
case 'integer':
|
|
686
700
|
condition = `Number.isInteger(obj${accessor})`
|
|
@@ -740,8 +754,7 @@ function buildMultiTypeSerializer (context, location, input) {
|
|
|
740
754
|
(
|
|
741
755
|
typeof ${input} === "object" &&
|
|
742
756
|
typeof ${input}.toString === "function" &&
|
|
743
|
-
${input}.toString !== Object.prototype.toString
|
|
744
|
-
!(${input} instanceof Date)
|
|
757
|
+
${input}.toString !== Object.prototype.toString
|
|
745
758
|
)
|
|
746
759
|
)
|
|
747
760
|
${nestedResult}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fast-json-stringify",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.10.0",
|
|
4
4
|
"description": "Stringify your JSON at max speed",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -16,7 +16,10 @@
|
|
|
16
16
|
"test:unit": "tap",
|
|
17
17
|
"test": "npm run test:unit && npm run test:typescript"
|
|
18
18
|
},
|
|
19
|
-
"precommit": [
|
|
19
|
+
"precommit": [
|
|
20
|
+
"lint",
|
|
21
|
+
"test"
|
|
22
|
+
],
|
|
20
23
|
"repository": {
|
|
21
24
|
"type": "git",
|
|
22
25
|
"url": "git+https://github.com/fastify/fast-json-stringify.git"
|
|
@@ -35,7 +38,7 @@
|
|
|
35
38
|
"homepage": "https://github.com/fastify/fast-json-stringify#readme",
|
|
36
39
|
"devDependencies": {
|
|
37
40
|
"@fastify/pre-commit": "^2.0.2",
|
|
38
|
-
"@sinclair/typebox": "^0.
|
|
41
|
+
"@sinclair/typebox": "^0.32.3",
|
|
39
42
|
"benchmark": "^2.1.4",
|
|
40
43
|
"cli-select": "^1.1.2",
|
|
41
44
|
"compile-json-stringify": "^0.1.2",
|
package/test/array.test.js
CHANGED
|
@@ -31,12 +31,36 @@ function buildTest (schema, toStringify, options) {
|
|
|
31
31
|
const stringify = build(schema, options)
|
|
32
32
|
const output = stringify(toStringify)
|
|
33
33
|
|
|
34
|
-
t.same(JSON.parse(output), toStringify)
|
|
34
|
+
t.same(JSON.parse(output), JSON.parse(JSON.stringify(toStringify)))
|
|
35
35
|
t.equal(output, JSON.stringify(toStringify))
|
|
36
36
|
t.ok(validate(JSON.parse(output)), 'valid schema')
|
|
37
37
|
})
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
buildTest({
|
|
41
|
+
title: 'dates tuple',
|
|
42
|
+
type: 'object',
|
|
43
|
+
properties: {
|
|
44
|
+
dates: {
|
|
45
|
+
type: 'array',
|
|
46
|
+
minItems: 2,
|
|
47
|
+
maxItems: 2,
|
|
48
|
+
items: [
|
|
49
|
+
{
|
|
50
|
+
type: 'string',
|
|
51
|
+
format: 'date-time'
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
type: 'string',
|
|
55
|
+
format: 'date-time'
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}, {
|
|
61
|
+
dates: [new Date(1), new Date(2)]
|
|
62
|
+
})
|
|
63
|
+
|
|
40
64
|
buildTest({
|
|
41
65
|
title: 'string array',
|
|
42
66
|
type: 'object',
|
package/test/toJSON.test.js
CHANGED
|
@@ -127,7 +127,7 @@ test('not fail on null sub-object declared nullable', (t) => {
|
|
|
127
127
|
t.equal('{"product":null}', stringify(object))
|
|
128
128
|
})
|
|
129
129
|
|
|
130
|
-
test('
|
|
130
|
+
test('on non nullable null sub-object it should coerce to {}', (t) => {
|
|
131
131
|
t.plan(1)
|
|
132
132
|
|
|
133
133
|
const stringify = build({
|
|
@@ -148,10 +148,12 @@ test('throw an error on non nullable null sub-object', (t) => {
|
|
|
148
148
|
const object = {
|
|
149
149
|
product: null
|
|
150
150
|
}
|
|
151
|
-
|
|
151
|
+
|
|
152
|
+
const result = stringify(object)
|
|
153
|
+
t.equal(result, JSON.stringify({ product: {} }))
|
|
152
154
|
})
|
|
153
155
|
|
|
154
|
-
test('
|
|
156
|
+
test('on non nullable null object it should coerce to {}', (t) => {
|
|
155
157
|
t.plan(1)
|
|
156
158
|
|
|
157
159
|
const stringify = build({
|
|
@@ -170,5 +172,32 @@ test('throw an error on non nullable null object', (t) => {
|
|
|
170
172
|
}
|
|
171
173
|
}
|
|
172
174
|
})
|
|
173
|
-
|
|
175
|
+
|
|
176
|
+
const result = stringify(null)
|
|
177
|
+
t.equal(result, '{}')
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
test('on non-nullable null object it should skip rendering, skipping required fields checks', (t) => {
|
|
181
|
+
t.plan(1)
|
|
182
|
+
|
|
183
|
+
const stringify = build({
|
|
184
|
+
title: 'simple object',
|
|
185
|
+
nullable: false,
|
|
186
|
+
type: 'object',
|
|
187
|
+
properties: {
|
|
188
|
+
product: {
|
|
189
|
+
nullable: false,
|
|
190
|
+
type: 'object',
|
|
191
|
+
properties: {
|
|
192
|
+
name: {
|
|
193
|
+
type: 'string'
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
required: ['product']
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
const result = stringify(null)
|
|
202
|
+
t.equal(result, '{}')
|
|
174
203
|
})
|
package/test/typesArray.test.js
CHANGED
|
@@ -467,7 +467,7 @@ test('class instance that is simultaneously a string and a json', (t) => {
|
|
|
467
467
|
t.equal(valueObj, '{"simultaneously":{"foo":"hello"}}')
|
|
468
468
|
})
|
|
469
469
|
|
|
470
|
-
test('should throw an error when type is array and object is null', (t) => {
|
|
470
|
+
test('should not throw an error when type is array and object is null, it should instead coerce to []', (t) => {
|
|
471
471
|
t.plan(1)
|
|
472
472
|
const schema = {
|
|
473
473
|
type: 'object',
|
|
@@ -482,7 +482,8 @@ test('should throw an error when type is array and object is null', (t) => {
|
|
|
482
482
|
}
|
|
483
483
|
|
|
484
484
|
const stringify = build(schema)
|
|
485
|
-
|
|
485
|
+
const result = stringify({ arr: null })
|
|
486
|
+
t.equal(result, JSON.stringify({ arr: [] }))
|
|
486
487
|
})
|
|
487
488
|
|
|
488
489
|
test('should throw an error when type is array and object is not an array', (t) => {
|