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 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 || randomUUID(),
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 = `merged_${randomUUID()}`
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.9.1",
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": ["lint", "test"],
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.31.1",
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",
@@ -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',
@@ -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('throw an error on non nullable null sub-object', (t) => {
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
- t.throws(() => { stringify(object) })
151
+
152
+ const result = stringify(object)
153
+ t.equal(result, JSON.stringify({ product: {} }))
152
154
  })
153
155
 
154
- test('throw an error on non nullable null object', (t) => {
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
- t.throws(() => { stringify(null) })
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
  })
@@ -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
- t.throws(() => stringify({ arr: null }), new TypeError('The value of \'#/properties/arr\' does not match schema definition.'))
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) => {