fast-json-stringify 2.7.11 → 3.0.1

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.
@@ -2,6 +2,10 @@ version: 2
2
2
  updates:
3
3
  - package-ecosystem: github-actions
4
4
  directory: '/'
5
+ ignore:
6
+ - dependency-name: "actions/*"
7
+ update-types:
8
+ ["version-update:semver-minor", "version-update:semver-patch"]
5
9
  schedule:
6
10
  interval: daily
7
11
  open-pull-requests-limit: 10
@@ -15,14 +15,14 @@ jobs:
15
15
  runs-on: ${{ matrix.os }}
16
16
  strategy:
17
17
  matrix:
18
- node-version: [10, 12, 13, 14, 16]
18
+ node-version: [14, 16, 17]
19
19
  os: [macos-latest, ubuntu-latest, windows-latest]
20
20
 
21
21
  steps:
22
- - uses: actions/checkout@v2.3.4
22
+ - uses: actions/checkout@v2
23
23
 
24
24
  - name: Use Node.js
25
- uses: actions/setup-node@v2.4.0
25
+ uses: actions/setup-node@v2
26
26
  with:
27
27
  node-version: ${{ matrix.node-version }}
28
28
 
@@ -37,7 +37,11 @@ jobs:
37
37
  automerge:
38
38
  needs: test
39
39
  runs-on: ubuntu-latest
40
+ permissions:
41
+ pull-requests: write
42
+ contents: write
40
43
  steps:
41
- - uses: fastify/github-action-merge-dependabot@v2.5.0
44
+ - uses: fastify/github-action-merge-dependabot@v3
42
45
  with:
43
46
  github-token: ${{ secrets.GITHUB_TOKEN }}
47
+ target: minor
package/README.md CHANGED
@@ -7,7 +7,14 @@
7
7
  [![NPM downloads](https://img.shields.io/npm/dm/fast-json-stringify.svg?style=flat)](https://www.npmjs.com/package/fast-json-stringify)
8
8
 
9
9
 
10
- __fast-json-stringify__ is significantly faster than `JSON.stringify()` for small payloads. Its performance advantage shrinks as your payload grows. It pairs well with [__flatstr__](https://www.npmjs.com/package/flatstr), which triggers a V8 optimization that improves performance when eventually converting the string to a `Buffer`.
10
+ __fast-json-stringify__ is significantly faster than `JSON.stringify()` for small payloads.
11
+ Its performance advantage shrinks as your payload grows.
12
+ It pairs well with [__flatstr__](https://www.npmjs.com/package/flatstr), which triggers a V8 optimization that improves performance when eventually converting the string to a `Buffer`.
13
+
14
+
15
+ ### How it works
16
+
17
+ fast-json-stringify requires a [JSON Schema Draft 7](https://json-schema.org/specification-links.html#draft-7) input to generate a fast `stringify` function.
11
18
 
12
19
  ##### Benchmarks
13
20
 
@@ -15,22 +22,28 @@ __fast-json-stringify__ is significantly faster than `JSON.stringify()` for smal
15
22
  - Node.js `v16.9.1`
16
23
 
17
24
  ```
18
- FJS creation x 6,040 ops/sec ±1.17% (91 runs sampled)
19
-
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
-
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
-
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
-
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)
25
+ FJS creation x 8,443 ops/sec ±1.01% (90 runs sampled)
26
+ CJS creation x 183,219 ops/sec ±0.13% (96 runs sampled)
27
+ AJV Serialize creation x 83,541,848 ops/sec ±0.24% (98 runs sampled)
28
+ JSON.stringify array x 5,363 ops/sec ±0.11% (100 runs sampled)
29
+ fast-json-stringify array x 6,747 ops/sec ±0.13% (98 runs sampled)
30
+ compile-json-stringify array x 7,121 ops/sec ±0.42% (98 runs sampled)
31
+ AJV Serialize array x 7,533 ops/sec ±0.13% (98 runs sampled)
32
+ JSON.stringify long string x 16,461 ops/sec ±0.12% (98 runs sampled)
33
+ fast-json-stringify long string x 16,443 ops/sec ±0.37% (99 runs sampled)
34
+ compile-json-stringify long string x 16,458 ops/sec ±0.09% (98 runs sampled)
35
+ AJV Serialize long string x 21,433 ops/sec ±0.08% (95 runs sampled)
36
+ JSON.stringify short string x 12,035,664 ops/sec ±0.62% (96 runs sampled)
37
+ fast-json-stringify short string x 38,281,060 ops/sec ±0.24% (98 runs sampled)
38
+ compile-json-stringify short string x 32,388,037 ops/sec ±0.27% (97 runs sampled)
39
+ AJV Serialize short string x 32,288,612 ops/sec ±0.32% (95 runs sampled)
40
+ JSON.stringify obj x 3,068,185 ops/sec ±0.16% (98 runs sampled)
41
+ fast-json-stringify obj x 10,082,694 ops/sec ±0.10% (97 runs sampled)
42
+ compile-json-stringify obj x 17,037,963 ops/sec ±1.17% (97 runs sampled)
43
+ AJV Serialize obj x 9,660,041 ops/sec ±0.11% (97 runs sampled)
44
+ JSON stringify date x 1,084,008 ops/sec ±0.16% (98 runs sampled)
45
+ fast-json-stringify date format x 1,781,044 ops/sec ±0.48% (99 runs sampled)
46
+ compile-json-stringify date format x 1,086,187 ops/sec ±0.16% (99 runs sampled)
34
47
  ```
35
48
 
36
49
  #### Table of contents:
@@ -43,7 +56,7 @@ fast-json-stringify date format x 1,674,498 ops/sec ±0.12% (99 runs sampled)
43
56
  - <a href="#missingFields">`Missing fields`</a>
44
57
  - <a href="#patternProperties">`Pattern Properties`</a>
45
58
  - <a href="#additionalProperties">`Additional Properties`</a>
46
- - <a href="#anyof">`AnyOf`</a>
59
+ - <a href="#anyof">`AnyOf` and `OneOf`</a>
47
60
  - <a href="#ref">`Reuse - $ref`</a>
48
61
  - <a href="#long">`Long integers`</a>
49
62
  - <a href="#integer">`Integers`</a>
@@ -102,7 +115,7 @@ const stringify = fastJson(mySchema, {
102
115
  ```
103
116
 
104
117
  - `schema`: external schemas references by $ref property. [More details](#ref)
105
- - `ajv`: ajv instance's settings for those properties that require `ajv`. [More details](#anyof)
118
+ - `ajv`: [ajv v8 instance's settings](https://ajv.js.org/options.html) for those properties that require `ajv`. [More details](#anyof)
106
119
  - `rounding`: setup how the `integer` types will be rounded when not integers. [More details](#integer)
107
120
 
108
121
 
@@ -111,7 +124,7 @@ const stringify = fastJson(mySchema, {
111
124
  <a name="fastJsonStringify"></a>
112
125
  ### fastJsonStringify(schema)
113
126
 
114
- Build a `stringify()` function based on [jsonschema](https://json-schema.org/).
127
+ Build a `stringify()` function based on [jsonschema draft 7 spec](https://json-schema.org/specification-links.html#draft-7).
115
128
 
116
129
  Supported types:
117
130
 
@@ -307,11 +320,11 @@ const obj = {
307
320
  console.log(stringify(obj)) // '{"nickname":"nick","matchfoo":"42","otherfoo":"str","matchnum":3,"nomatchstr":"valar morghulis",nomatchint:"313"}'
308
321
  ```
309
322
 
310
- #### AnyOf
323
+ #### AnyOf and OneOf
311
324
 
312
- `fast-json-stringify` supports the anyOf keyword as defined by JSON schema. *anyOf* must be an array of valid JSON schemas. The different schemas will be tested in the specified order. The more schemas `stringify` has to try before finding a match, the slower it will be.
325
+ `fast-json-stringify` supports the **anyOf** and **oneOf** keywords as defined by JSON schema. Both must be an array of valid JSON schemas. The different schemas will be tested in the specified order. The more schemas `stringify` has to try before finding a match, the slower it will be.
313
326
 
314
- *anyOf* uses [ajv](https://www.npmjs.com/package/ajv) as a JSON schema validator to find the schema that matches the data. This has an impact on performance—only use it as a last resort.
327
+ *anyOf* and *oneOf* use [ajv](https://www.npmjs.com/package/ajv) as a JSON schema validator to find the schema that matches the data. This has an impact on performance—only use it as a last resort.
315
328
 
316
329
  Example:
317
330
  ```javascript
@@ -521,46 +534,7 @@ const stringify = fastJson(schema, { schema: externalSchema })
521
534
 
522
535
  <a name="long"></a>
523
536
  #### Long integers
524
- By default the library will automatically handle [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) from Node.js v10.3 and above.
525
- If you can't use BigInts in your environment, long integers (64-bit) are also supported using the [long](https://github.com/dcodeIO/long.js) module.
526
- Example:
527
- ```javascript
528
- // => using native BigInt
529
- const stringify = fastJson({
530
- title: 'Example Schema',
531
- type: 'object',
532
- properties: {
533
- id: {
534
- type: 'integer'
535
- }
536
- }
537
- })
538
-
539
- const obj = {
540
- id: 18446744073709551615n
541
- }
542
-
543
- console.log(stringify(obj)) // '{"id":18446744073709551615}'
544
-
545
- // => using the long library
546
- const Long = require('long')
547
-
548
- const stringify = fastJson({
549
- title: 'Example Schema',
550
- type: 'object',
551
- properties: {
552
- id: {
553
- type: 'integer'
554
- }
555
- }
556
- })
557
-
558
- const obj = {
559
- id: Long.fromString('18446744073709551615', true)
560
- }
561
-
562
- console.log(stringify(obj)) // '{"id":18446744073709551615}'
563
- ```
537
+ By default the library will handle automatically [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
564
538
 
565
539
  <a name="integer"></a>
566
540
  #### Integers
package/bench.js CHANGED
@@ -38,6 +38,21 @@ const schemaCJS = {
38
38
  }
39
39
  }
40
40
 
41
+ const schemaAJVJTD = {
42
+ properties: {
43
+ firstName: {
44
+ type: 'string'
45
+ },
46
+ lastName: {
47
+ type: 'string',
48
+ nullable: true
49
+ },
50
+ age: {
51
+ type: 'uint8'
52
+ }
53
+ }
54
+ }
55
+
41
56
  const arraySchema = {
42
57
  title: 'array schema',
43
58
  type: 'array',
@@ -50,6 +65,10 @@ const arraySchemaCJS = {
50
65
  items: schemaCJS
51
66
  }
52
67
 
68
+ const arraySchemaAJVJTD = {
69
+ elements: schemaAJVJTD
70
+ }
71
+
53
72
  const dateFormatSchema = {
54
73
  description: 'Date of birth',
55
74
  type: 'string',
@@ -85,6 +104,12 @@ const stringifyDate = FJS(dateFormatSchema)
85
104
  const stringifyString = FJS({ type: 'string' })
86
105
  let str = ''
87
106
 
107
+ const Ajv = require('ajv/dist/jtd')
108
+ const ajv = new Ajv()
109
+ const ajvSerialize = ajv.compileSerializer(schemaAJVJTD)
110
+ const ajvSerializeArray = ajv.compileSerializer(arraySchemaAJVJTD)
111
+ const ajvSerializeString = ajv.compileSerializer({ type: 'string' })
112
+
88
113
  // eslint-disable-next-line
89
114
  for (var i = 0; i < 10000; i++) {
90
115
  str += i
@@ -105,6 +130,9 @@ suite.add('FJS creation', function () {
105
130
  suite.add('CJS creation', function () {
106
131
  CJS(schemaCJS)
107
132
  })
133
+ suite.add('AJV Serialize creation', function () {
134
+ ajv.compileSerializer(schemaAJVJTD)
135
+ })
108
136
 
109
137
  suite.add('JSON.stringify array', function () {
110
138
  JSON.stringify(multiArray)
@@ -118,6 +146,10 @@ suite.add('compile-json-stringify array', function () {
118
146
  CJSStringifyArray(multiArray)
119
147
  })
120
148
 
149
+ suite.add('AJV Serialize array', function () {
150
+ ajvSerializeArray(multiArray)
151
+ })
152
+
121
153
  suite.add('JSON.stringify long string', function () {
122
154
  JSON.stringify(str)
123
155
  })
@@ -130,6 +162,10 @@ suite.add('compile-json-stringify long string', function () {
130
162
  CJSStringifyString(str)
131
163
  })
132
164
 
165
+ suite.add('AJV Serialize long string', function () {
166
+ ajvSerializeString(str)
167
+ })
168
+
133
169
  suite.add('JSON.stringify short string', function () {
134
170
  JSON.stringify('hello world')
135
171
  })
@@ -142,6 +178,10 @@ suite.add('compile-json-stringify short string', function () {
142
178
  CJSStringifyString('hello world')
143
179
  })
144
180
 
181
+ suite.add('AJV Serialize short string', function () {
182
+ ajvSerializeString('hello world')
183
+ })
184
+
145
185
  suite.add('JSON.stringify obj', function () {
146
186
  JSON.stringify(obj)
147
187
  })
@@ -154,6 +194,10 @@ suite.add('compile-json-stringify obj', function () {
154
194
  CJSStringify(obj)
155
195
  })
156
196
 
197
+ suite.add('AJV Serialize obj', function () {
198
+ ajvSerialize(obj)
199
+ })
200
+
157
201
  suite.add('JSON stringify date', function () {
158
202
  JSON.stringify(date)
159
203
  })
@@ -1,21 +1,26 @@
1
1
  'use strict'
2
2
 
3
3
  const Ajv = require('ajv')
4
+ const standaloneCode = require('ajv/dist/standalone').default
5
+ const ajvFormats = require('ajv-formats')
4
6
  const fs = require('fs')
5
7
  const path = require('path')
6
- const pack = require('ajv-pack')
7
8
 
8
9
  const ajv = new Ajv({
9
- sourceCode: true // this option is required by ajv-pack
10
+ addUsedSchema: false,
11
+ allowUnionTypes: true,
12
+ code: {
13
+ source: true,
14
+ lines: true,
15
+ optimize: 3
16
+ }
10
17
  })
18
+ ajvFormats(ajv)
11
19
 
12
- const validate = ajv.compile(require('ajv/lib/refs/json-schema-draft-07.json'))
20
+ const schema = require('ajv/lib/refs/json-schema-draft-07.json')
21
+ const validate = ajv.compile(schema)
22
+ const validationCode = standaloneCode(ajv, validate)
13
23
 
14
- const moduleCode = `// This file is autogenerated by ${path.basename(__filename)}, do not edit
15
-
16
- function nop () { return true }
17
-
18
- ${pack(ajv, validate).replace(/root\.refVal\[0\]/gm, 'nop')}
19
- `
24
+ const moduleCode = `/* CODE GENERATED BY '${path.basename(__filename)}' DO NOT EDIT! */\n${validationCode}`
20
25
 
21
26
  fs.writeFileSync(path.join(__dirname, 'schema-validator.js'), moduleCode)
package/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  /* eslint no-prototype-builtins: 0 */
4
4
 
5
5
  const Ajv = require('ajv')
6
+ const ajvFormats = require('ajv-formats')
6
7
  const merge = require('deepmerge')
7
8
  const clone = require('rfdc')({ proto: true })
8
9
  const fjsCloned = Symbol('fast-json-stringify.cloned')
@@ -10,13 +11,6 @@ const fjsCloned = Symbol('fast-json-stringify.cloned')
10
11
  const validate = require('./schema-validator')
11
12
  let stringSimilarity = null
12
13
 
13
- let isLong
14
- try {
15
- isLong = require('long').isLong
16
- } catch (e) {
17
- isLong = null
18
- }
19
-
20
14
  const addComma = `
21
15
  if (addComma) {
22
16
  json += ','
@@ -33,7 +27,7 @@ function isValidSchema (schema, name) {
33
27
  name = ''
34
28
  }
35
29
  const first = validate.errors[0]
36
- const err = new Error(`${name}schema is invalid: data${first.dataPath} ${first.message}`)
30
+ const err = new Error(`${name}schema is invalid: data${first.instancePath} ${first.message}`)
37
31
  err.errors = isValidSchema.errors
38
32
  throw err
39
33
  }
@@ -47,10 +41,12 @@ function mergeLocation (source, dest) {
47
41
  }
48
42
  }
49
43
 
50
- const referenceSerializersMap = new Map()
44
+ const arrayItemsReferenceSerializersMap = new Map()
45
+ const objectReferenceSerializersMap = new Map()
51
46
 
52
47
  function build (schema, options) {
53
- referenceSerializersMap.clear()
48
+ arrayItemsReferenceSerializersMap.clear()
49
+ objectReferenceSerializersMap.clear()
54
50
  options = options || {}
55
51
  isValidSchema(schema)
56
52
  if (options.schema) {
@@ -77,7 +73,39 @@ function build (schema, options) {
77
73
  code += `
78
74
  ${asFunctions}
79
75
 
80
- var isLong = ${isLong ? isLong.toString() : false}
76
+
77
+ /**
78
+ * Used by schemas that are dependant on calling 'ajv.validate' during runtime,
79
+ * it stores the value of the '$id' property of the schema (if it has it) inside
80
+ * a cache which is used to figure out if the schema was compiled into a validator
81
+ * by ajv on a previous call, if it was then the '$id' string will be used to
82
+ * invoke 'ajv.validate', this allows:
83
+ *
84
+ * 1. Schemas that depend on ajv.validate calls to leverage ajv caching system.
85
+ * 2. To avoid errors, since directly invoking 'ajv.validate' with the same
86
+ * schema (that contains an '$id' property) twice will throw an error.
87
+ */
88
+ const $validateWithAjv = (function() {
89
+ const cache = new Set()
90
+
91
+ return function (schema, target) {
92
+ const id = schema.$id
93
+
94
+ if (!id) {
95
+ return ajv.validate(schema, target)
96
+ }
97
+
98
+ const cached = cache.has(id)
99
+
100
+ if (cached) {
101
+ return ajv.validate(id, target)
102
+ } else {
103
+ cache.add(id)
104
+ return ajv.validate(schema, target)
105
+ }
106
+ }
107
+ })()
108
+
81
109
 
82
110
  function parseInteger(int) { return Math.${intParseFunctionName}(int) }
83
111
  `
@@ -136,7 +164,9 @@ function build (schema, options) {
136
164
  return ${main}
137
165
  `
138
166
 
139
- const dependencies = [new Ajv(options.ajv)]
167
+ const ajvInstance = new Ajv(options.ajv)
168
+ ajvFormats(ajvInstance)
169
+ const dependencies = [ajvInstance]
140
170
  const dependenciesName = ['ajv']
141
171
  dependenciesName.push(code)
142
172
 
@@ -147,7 +177,8 @@ function build (schema, options) {
147
177
  return dependenciesName
148
178
  }
149
179
 
150
- referenceSerializersMap.clear()
180
+ arrayItemsReferenceSerializersMap.clear()
181
+ objectReferenceSerializersMap.clear()
151
182
 
152
183
  return (Function.apply(null, dependenciesName).apply(null, dependencies))
153
184
  }
@@ -239,9 +270,7 @@ function $asNull () {
239
270
  }
240
271
 
241
272
  function $asInteger (i) {
242
- if (isLong && isLong(i)) {
243
- return i.toString()
244
- } else if (typeof i === 'bigint') {
273
+ if (typeof i === 'bigint') {
245
274
  return i.toString()
246
275
  } else if (Number.isInteger(i)) {
247
276
  return $asNumber(i)
@@ -399,51 +428,60 @@ function addPatternProperties (location) {
399
428
  } catch (err) {
400
429
  throw new Error(`${err.message}. Found at ${regex} matching ${JSON.stringify(pp[regex])}`)
401
430
  }
402
- code += `
403
- if (/${regex.replace(/\\*\//g, '\\/')}/.test(keys[i])) {
404
- `
431
+
432
+ const ifPpKeyExists = `if (/${regex.replace(/\\*\//g, '\\/')}/.test(keys[i])) {`
433
+
405
434
  if (type === 'object') {
406
435
  code += `${buildObject(ppLocation, '', 'buildObjectPP' + index)}
436
+ ${ifPpKeyExists}
407
437
  ${addComma}
408
438
  json += $asString(keys[i]) + ':' + buildObjectPP${index}(obj[keys[i]])
409
439
  `
410
440
  } else if (type === 'array') {
411
441
  code += `${buildArray(ppLocation, '', 'buildArrayPP' + index)}
442
+ ${ifPpKeyExists}
412
443
  ${addComma}
413
444
  json += $asString(keys[i]) + ':' + buildArrayPP${index}(obj[keys[i]])
414
445
  `
415
446
  } else if (type === 'null') {
416
447
  code += `
448
+ ${ifPpKeyExists}
417
449
  ${addComma}
418
450
  json += $asString(keys[i]) +':null'
419
451
  `
420
452
  } else if (type === 'string') {
421
453
  code += `
454
+ ${ifPpKeyExists}
422
455
  ${addComma}
423
456
  json += $asString(keys[i]) + ':' + ${stringSerializer}(obj[keys[i]])
424
457
  `
425
458
  } else if (type === 'integer') {
426
459
  code += `
460
+ ${ifPpKeyExists}
427
461
  ${addComma}
428
462
  json += $asString(keys[i]) + ':' + $asInteger(obj[keys[i]])
429
463
  `
430
464
  } else if (type === 'number') {
431
465
  code += `
466
+ ${ifPpKeyExists}
432
467
  ${addComma}
433
468
  json += $asString(keys[i]) + ':' + $asNumber(obj[keys[i]])
434
469
  `
435
470
  } else if (type === 'boolean') {
436
471
  code += `
472
+ ${ifPpKeyExists}
437
473
  ${addComma}
438
474
  json += $asString(keys[i]) + ':' + $asBoolean(obj[keys[i]])
439
475
  `
440
476
  } else if (type === undefined) {
441
477
  code += `
478
+ ${ifPpKeyExists}
442
479
  ${addComma}
443
480
  json += $asString(keys[i]) + ':' + $asAny(obj[keys[i]])
444
481
  `
445
482
  } else {
446
483
  code += `
484
+ ${ifPpKeyExists}
447
485
  throw new Error('Cannot coerce ' + obj[keys[i]] + ' to ' + ${JSON.stringify(type)})
448
486
  `
449
487
  }
@@ -506,22 +544,11 @@ function additionalProperty (location) {
506
544
  } else if (type === 'integer') {
507
545
  code += `
508
546
  var t = Number(obj[keys[i]])
547
+ if (!isNaN(t)) {
548
+ ${addComma}
549
+ json += $asString(keys[i]) + ':' + t
550
+ }
509
551
  `
510
- if (isLong) {
511
- code += `
512
- if (isLong(obj[keys[i]]) || !isNaN(t)) {
513
- ${addComma}
514
- json += $asString(keys[i]) + ':' + $asInteger(obj[keys[i]])
515
- }
516
- `
517
- } else {
518
- code += `
519
- if (!isNaN(t)) {
520
- ${addComma}
521
- json += $asString(keys[i]) + ':' + t
522
- }
523
- `
524
- }
525
552
  } else if (type === 'number') {
526
553
  code += `
527
554
  var t = Number(obj[keys[i]])
@@ -723,33 +750,12 @@ function buildCode (location, code, laterCode, name) {
723
750
  } else if (type === 'integer') {
724
751
  code += `
725
752
  var rendered = false
726
- `
727
- if (isLong) {
728
- code += `
729
- if (isLong(obj[${sanitized}])) {
730
- ${addComma}
731
- json += ${asString} + ':' + obj[${sanitized}].toString()
732
- rendered = true
733
- } else {
734
- var t = Number(obj[${sanitized}])
735
- if (!isNaN(t)) {
736
- ${addComma}
737
- json += ${asString} + ':' + t
738
- rendered = true
739
- }
740
- }
741
- `
742
- } else {
743
- code += `
744
- var t = $asInteger(obj[${sanitized}])
745
- if (!isNaN(t)) {
746
- ${addComma}
747
- json += ${asString} + ':' + t
748
- rendered = true
749
- }
750
- `
751
- }
752
- code += `
753
+ var t = $asInteger(obj[${sanitized}])
754
+ if (!isNaN(t)) {
755
+ ${addComma}
756
+ json += ${asString} + ':' + t
757
+ rendered = true
758
+ }
753
759
  if (rendered) {
754
760
  `
755
761
  } else {
@@ -807,6 +813,12 @@ function buildCode (location, code, laterCode, name) {
807
813
  `
808
814
  }
809
815
 
816
+ if (schema.allOf) {
817
+ const builtCode = buildCodeWithAllOfs(location, code, laterCode, name)
818
+ code = builtCode.code
819
+ laterCode = builtCode.laterCode
820
+ }
821
+
810
822
  return { code: code, laterCode: laterCode }
811
823
  }
812
824
 
@@ -863,7 +875,7 @@ function addIfThenElse (location, name) {
863
875
  let mergedLocation = mergeLocation(location, { schema: merged })
864
876
 
865
877
  code += `
866
- valid = ajv.validate(${JSON.stringify(i)}, obj)
878
+ valid = $validateWithAjv(${JSON.stringify(i)}, obj)
867
879
  if (valid) {
868
880
  `
869
881
  if (merged.if && merged.then) {
@@ -922,6 +934,16 @@ function buildObject (location, code, name) {
922
934
  }
923
935
  `
924
936
  }
937
+
938
+ if (objectReferenceSerializersMap.has(schema)) {
939
+ code += `
940
+ return ${objectReferenceSerializersMap.get(schema)}(input)
941
+ }
942
+ `
943
+ return code
944
+ }
945
+ objectReferenceSerializersMap.set(schema, name)
946
+
925
947
  code += `
926
948
  var obj = ${toJSON('input')}
927
949
  var json = '{'
@@ -978,14 +1000,14 @@ function buildArray (location, code, name, key = null) {
978
1000
  location = refFinder(schema.items.$ref, location)
979
1001
  schema.items = location.schema
980
1002
 
981
- if (referenceSerializersMap.has(schema.items)) {
1003
+ if (arrayItemsReferenceSerializersMap.has(schema.items)) {
982
1004
  code += `
983
- return ${referenceSerializersMap.get(schema.items)}(obj)
1005
+ return ${arrayItemsReferenceSerializersMap.get(schema.items)}(obj)
984
1006
  }
985
1007
  `
986
1008
  return code
987
1009
  }
988
- referenceSerializersMap.set(schema.items, name)
1010
+ arrayItemsReferenceSerializersMap.set(schema.items, name)
989
1011
  }
990
1012
 
991
1013
  let result = { code: '', laterCode: '' }
@@ -1203,7 +1225,7 @@ function nested (laterCode, name, key, location, subKey, isArray) {
1203
1225
  // 2. `nested`, through `buildCode`, replaces any reference in object properties with the actual schema
1204
1226
  // (see https://github.com/fastify/fast-json-stringify/blob/6da3b3e8ac24b1ca5578223adedb4083b7adf8db/index.js#L631)
1205
1227
  code += `
1206
- ${index === 0 ? 'if' : 'else if'}(ajv.validate(${JSON.stringify(location.schema)}, ${testValue}))
1228
+ ${index === 0 ? 'if' : 'else if'}($validateWithAjv(${JSON.stringify(location.schema)}, ${testValue}))
1207
1229
  ${nestedResult.code}
1208
1230
  `
1209
1231
  laterCode = nestedResult.laterCode
@@ -1220,7 +1242,7 @@ function nested (laterCode, name, key, location, subKey, isArray) {
1220
1242
  const testValue = testSerializer !== undefined ? `${testSerializer}(obj${accessor}, true)` : `obj${accessor}`
1221
1243
  // see comment on anyOf about dereferencing the schema before calling ajv.validate
1222
1244
  code += `
1223
- ${index === 0 ? 'if' : 'else if'}(ajv.validate(${JSON.stringify(location.schema)}, ${testValue}))
1245
+ ${index === 0 ? 'if' : 'else if'}($validateWithAjv(${JSON.stringify(location.schema)}, ${testValue}))
1224
1246
  ${nestedResult.code}
1225
1247
  `
1226
1248
  laterCode = nestedResult.laterCode
@@ -1335,7 +1357,9 @@ module.exports.restore = function (debugModeStr, options = {}) {
1335
1357
  const args = []
1336
1358
  if (debugModeStr.startsWith('ajv')) {
1337
1359
  dependencies.unshift('ajv')
1338
- args.push(new Ajv(options.ajv))
1360
+ const ajvInstance = new Ajv(options.ajv)
1361
+ ajvFormats(ajvInstance)
1362
+ args.push(ajvInstance)
1339
1363
  }
1340
1364
 
1341
1365
  // eslint-disable-next-line
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fast-json-stringify",
3
- "version": "2.7.11",
3
+ "version": "3.0.1",
4
4
  "description": "Stringify your JSON at max speed",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -30,11 +30,9 @@
30
30
  },
31
31
  "homepage": "https://github.com/fastify/fast-json-stringify#readme",
32
32
  "devDependencies": {
33
- "ajv-pack": "^0.3.1",
34
33
  "benchmark": "^2.1.4",
35
34
  "compile-json-stringify": "^0.1.2",
36
35
  "is-my-json-valid": "^2.20.0",
37
- "long": "^4.0.0",
38
36
  "moment": "^2.24.0",
39
37
  "pre-commit": "^1.2.2",
40
38
  "proxyquire": "^2.1.3",
@@ -45,7 +43,8 @@
45
43
  "webpack": "^5.40.0"
46
44
  },
47
45
  "dependencies": {
48
- "ajv": "^6.11.0",
46
+ "ajv": "^8.6.2",
47
+ "ajv-formats": "^2.1.1",
49
48
  "deepmerge": "^4.2.2",
50
49
  "rfdc": "^1.2.0",
51
50
  "string-similarity": "^4.0.1"