fast-json-stringify 5.0.6 → 5.3.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/index.js CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  /* eslint no-prototype-builtins: 0 */
4
4
 
5
- const merge = require('deepmerge')
5
+ const merge = require('@fastify/deepmerge')()
6
6
  const clone = require('rfdc')({ proto: true })
7
- const fjsCloned = Symbol('fast-json-stringify.cloned')
8
7
  const { randomUUID } = require('crypto')
9
8
 
10
- const validate = require('./schema-validator')
11
- const Serializer = require('./serializer')
12
- const buildAjv = require('./ajv')
9
+ const validate = require('./lib/schema-validator')
10
+ const Serializer = require('./lib/serializer')
11
+ const Validator = require('./lib/validator')
12
+ const RefResolver = require('./lib/ref-resolver')
13
13
 
14
14
  let largeArraySize = 2e4
15
15
  let largeArrayMechanism = 'default'
@@ -57,20 +57,12 @@ function resolveRef (location, ref) {
57
57
  const schemaId = ref.slice(0, hashIndex) || location.schemaId
58
58
  const jsonPointer = ref.slice(hashIndex) || '#'
59
59
 
60
- const schemaRef = schemaId + jsonPointer
60
+ const schema = refResolver.getSchema(schemaId, jsonPointer)
61
61
 
62
- let ajvSchema
63
- try {
64
- ajvSchema = ajvInstance.getSchema(schemaRef)
65
- } catch (error) {
62
+ if (schema === undefined) {
66
63
  throw new Error(`Cannot find reference "${ref}"`)
67
64
  }
68
65
 
69
- if (ajvSchema === undefined) {
70
- throw new Error(`Cannot find reference "${ref}"`)
71
- }
72
-
73
- const schema = ajvSchema.schema
74
66
  if (schema.$ref !== undefined) {
75
67
  return resolveRef({ schema, schemaId, jsonPointer }, schema.$ref)
76
68
  }
@@ -78,45 +70,33 @@ function resolveRef (location, ref) {
78
70
  return { schema, schemaId, jsonPointer }
79
71
  }
80
72
 
81
- const arrayItemsReferenceSerializersMap = new Map()
82
- const objectReferenceSerializersMap = new Map()
73
+ const contextFunctionsNamesBySchema = new Map()
83
74
 
84
75
  let rootSchemaId = null
85
- let ajvInstance = null
76
+ let refResolver = null
77
+ let validator = null
86
78
  let contextFunctions = null
87
79
 
88
80
  function build (schema, options) {
89
- schema = clone(schema)
90
-
91
- arrayItemsReferenceSerializersMap.clear()
92
- objectReferenceSerializersMap.clear()
81
+ contextFunctionsNamesBySchema.clear()
93
82
 
94
83
  contextFunctions = []
95
84
  options = options || {}
96
85
 
97
- ajvInstance = buildAjv(options.ajv)
86
+ refResolver = new RefResolver()
87
+ validator = new Validator(options.ajv)
88
+
98
89
  rootSchemaId = schema.$id || randomUUID()
99
90
 
100
91
  isValidSchema(schema)
101
- extendDateTimeType(schema)
102
- ajvInstance.addSchema(schema, rootSchemaId)
92
+ validator.addSchema(schema, rootSchemaId)
93
+ refResolver.addSchema(schema, rootSchemaId)
103
94
 
104
95
  if (options.schema) {
105
- const externalSchemas = clone(options.schema)
106
-
107
- for (const key of Object.keys(externalSchemas)) {
108
- const externalSchema = externalSchemas[key]
109
- isValidSchema(externalSchema, key)
110
- extendDateTimeType(externalSchema)
111
-
112
- let schemaKey = externalSchema.$id || key
113
- if (externalSchema.$id !== undefined && externalSchema.$id[0] === '#') {
114
- schemaKey = key + externalSchema.$id // relative URI
115
- }
116
-
117
- if (ajvInstance.getSchema(schemaKey) === undefined) {
118
- ajvInstance.addSchema(externalSchema, schemaKey)
119
- }
96
+ for (const key of Object.keys(options.schema)) {
97
+ isValidSchema(options.schema[key], key)
98
+ validator.addSchema(options.schema[key], key)
99
+ refResolver.addSchema(options.schema[key], key)
120
100
  }
121
101
  }
122
102
 
@@ -157,31 +137,36 @@ function build (schema, options) {
157
137
  return main
158
138
  `
159
139
 
160
- const dependenciesName = ['ajv', 'serializer', contextFunctionCode]
140
+ const dependenciesName = ['validator', 'serializer', contextFunctionCode]
161
141
 
162
142
  if (options.debugMode) {
163
143
  options.mode = 'debug'
164
144
  }
165
145
 
166
146
  if (options.mode === 'debug') {
167
- return { code: dependenciesName.join('\n'), ajv: ajvInstance }
147
+ return {
148
+ validator,
149
+ serializer,
150
+ code: dependenciesName.join('\n'),
151
+ ajv: validator.ajv
152
+ }
168
153
  }
169
154
 
170
155
  if (options.mode === 'standalone') {
171
156
  // lazy load
172
- const buildStandaloneCode = require('./standalone')
173
- return buildStandaloneCode(options, ajvInstance, contextFunctionCode)
157
+ const buildStandaloneCode = require('./lib/standalone')
158
+ return buildStandaloneCode(options, validator, contextFunctionCode)
174
159
  }
175
160
 
176
161
  /* eslint no-new-func: "off" */
177
- const contextFunc = new Function('ajv', 'serializer', contextFunctionCode)
178
- const stringifyFunc = contextFunc(ajvInstance, serializer)
162
+ const contextFunc = new Function('validator', 'serializer', contextFunctionCode)
163
+ const stringifyFunc = contextFunc(validator, serializer)
179
164
 
180
- ajvInstance = null
165
+ refResolver = null
166
+ validator = null
181
167
  rootSchemaId = null
182
168
  contextFunctions = null
183
- arrayItemsReferenceSerializersMap.clear()
184
- objectReferenceSerializersMap.clear()
169
+ contextFunctionsNamesBySchema.clear()
185
170
 
186
171
  return stringifyFunc
187
172
  }
@@ -243,15 +228,6 @@ function inferTypeByKeyword (schema) {
243
228
  return schema.type
244
229
  }
245
230
 
246
- function getStringSerializer (format, nullable) {
247
- switch (format) {
248
- case 'date-time': return nullable ? 'serializer.asDatetimeNullable.bind(serializer)' : 'serializer.asDatetime.bind(serializer)'
249
- case 'date': return nullable ? 'serializer.asDateNullable.bind(serializer)' : 'serializer.asDate.bind(serializer)'
250
- case 'time': return nullable ? 'serializer.asTimeNullable.bind(serializer)' : 'serializer.asTime.bind(serializer)'
251
- default: return nullable ? 'serializer.asStringNullable.bind(serializer)' : 'serializer.asString.bind(serializer)'
252
- }
253
- }
254
-
255
231
  function addPatternProperties (location) {
256
232
  const schema = location.schema
257
233
  const pp = schema.patternProperties
@@ -350,17 +326,16 @@ function buildCode (location) {
350
326
  const propertiesLocation = mergeLocation(location, 'properties')
351
327
  Object.keys(schema.properties || {}).forEach((key) => {
352
328
  let propertyLocation = mergeLocation(propertiesLocation, key)
353
- if (schema.properties[key].$ref) {
354
- propertyLocation = resolveRef(location, schema.properties[key].$ref)
355
- schema.properties[key] = propertyLocation.schema
329
+ if (propertyLocation.$ref) {
330
+ propertyLocation = resolveRef(location, propertyLocation.$ref)
356
331
  }
357
332
 
358
- // Using obj['key'] !== undefined instead of obj.hasOwnProperty(prop) for perf reasons,
359
- // see https://github.com/mcollina/fast-json-stringify/pull/3 for discussion.
360
-
361
333
  const sanitized = JSON.stringify(key)
362
334
  const asString = JSON.stringify(sanitized)
363
335
 
336
+ // Using obj['key'] !== undefined instead of obj.hasOwnProperty(prop) for perf reasons,
337
+ // see https://github.com/mcollina/fast-json-stringify/pull/3 for discussion.
338
+
364
339
  code += `
365
340
  if (obj[${sanitized}] !== undefined) {
366
341
  ${addComma}
@@ -369,7 +344,7 @@ function buildCode (location) {
369
344
 
370
345
  code += buildValue(propertyLocation, `obj[${JSON.stringify(key)}]`)
371
346
 
372
- const defaultValue = schema.properties[key].default
347
+ const defaultValue = propertyLocation.schema.default
373
348
  if (defaultValue !== undefined) {
374
349
  code += `
375
350
  } else {
@@ -491,7 +466,8 @@ function mergeAllOfSchema (location, schema, mergedSchema) {
491
466
  delete mergedSchema.allOf
492
467
 
493
468
  mergedSchema.$id = `merged_${randomUUID()}`
494
- ajvInstance.addSchema(mergedSchema)
469
+ validator.addSchema(mergedSchema)
470
+ refResolver.addSchema(mergedSchema)
495
471
  location.schemaId = mergedSchema.$id
496
472
  location.jsonPointer = '#'
497
473
  }
@@ -520,7 +496,7 @@ function addIfThenElse (location) {
520
496
  const ifSchemaRef = ifLocation.schemaId + ifLocation.jsonPointer
521
497
 
522
498
  let code = `
523
- if (ajv.validate("${ifSchemaRef}", obj)) {
499
+ if (validator.validate("${ifSchemaRef}", obj)) {
524
500
  `
525
501
 
526
502
  const thenLocation = mergeLocation(location, 'then')
@@ -563,25 +539,18 @@ function toJSON (variableName) {
563
539
  function buildObject (location) {
564
540
  const schema = location.schema
565
541
 
566
- if (objectReferenceSerializersMap.has(schema)) {
567
- return objectReferenceSerializersMap.get(schema)
542
+ if (contextFunctionsNamesBySchema.has(schema)) {
543
+ return contextFunctionsNamesBySchema.get(schema)
568
544
  }
569
545
 
570
546
  const functionName = generateFuncName()
571
- objectReferenceSerializersMap.set(schema, functionName)
547
+ contextFunctionsNamesBySchema.set(schema, functionName)
572
548
 
573
549
  const schemaId = location.schemaId === rootSchemaId ? '' : location.schemaId
574
550
  let functionCode = `
575
551
  function ${functionName} (input) {
576
552
  // ${schemaId + location.jsonPointer}
577
553
  `
578
- if (schema.nullable) {
579
- functionCode += `
580
- if (input === null) {
581
- return 'null';
582
- }
583
- `
584
- }
585
554
 
586
555
  functionCode += `
587
556
  var obj = ${toJSON('input')}
@@ -606,33 +575,23 @@ function buildObject (location) {
606
575
  }
607
576
 
608
577
  function buildArray (location) {
609
- let schema = location.schema
610
-
611
- // default to any items type
612
- if (!schema.items) {
613
- schema.items = {}
614
- }
578
+ const schema = location.schema
615
579
 
616
580
  let itemsLocation = mergeLocation(location, 'items')
581
+ itemsLocation.schema = itemsLocation.schema || {}
617
582
 
618
- if (schema.items.$ref) {
619
- if (!schema[fjsCloned]) {
620
- location.schema = clone(location.schema)
621
- schema = location.schema
622
- schema[fjsCloned] = true
623
- }
624
-
625
- location = resolveRef(location, schema.items.$ref)
626
- itemsLocation = location
627
- schema.items = location.schema
583
+ if (itemsLocation.schema.$ref) {
584
+ itemsLocation = resolveRef(itemsLocation, itemsLocation.schema.$ref)
628
585
  }
629
586
 
630
- if (arrayItemsReferenceSerializersMap.has(schema.items)) {
631
- return arrayItemsReferenceSerializersMap.get(schema.items)
587
+ const itemsSchema = itemsLocation.schema
588
+
589
+ if (contextFunctionsNamesBySchema.has(schema)) {
590
+ return contextFunctionsNamesBySchema.get(schema)
632
591
  }
633
592
 
634
593
  const functionName = generateFuncName()
635
- arrayItemsReferenceSerializersMap.set(schema.items, functionName)
594
+ contextFunctionsNamesBySchema.set(schema, functionName)
636
595
 
637
596
  const schemaId = location.schemaId === rootSchemaId ? '' : location.schemaId
638
597
  let functionCode = `
@@ -640,14 +599,6 @@ function buildArray (location) {
640
599
  // ${schemaId + location.jsonPointer}
641
600
  `
642
601
 
643
- if (schema.nullable) {
644
- functionCode += `
645
- if (obj === null) {
646
- return 'null';
647
- }
648
- `
649
- }
650
-
651
602
  functionCode += `
652
603
  if (!Array.isArray(obj)) {
653
604
  throw new TypeError(\`The value '$\{obj}' does not match schema definition.\`)
@@ -657,8 +608,8 @@ function buildArray (location) {
657
608
 
658
609
  if (!schema.additionalItems) {
659
610
  functionCode += `
660
- if (arrayLength > ${schema.items.length}) {
661
- throw new Error(\`Item at ${schema.items.length} does not match schema definition.\`)
611
+ if (arrayLength > ${itemsSchema.length}) {
612
+ throw new Error(\`Item at ${itemsSchema.length} does not match schema definition.\`)
662
613
  }
663
614
  `
664
615
  }
@@ -675,9 +626,9 @@ function buildArray (location) {
675
626
  let jsonOutput = ''
676
627
  `
677
628
 
678
- if (Array.isArray(schema.items)) {
679
- for (let i = 0; i < schema.items.length; i++) {
680
- const item = schema.items[i]
629
+ if (Array.isArray(itemsSchema)) {
630
+ for (let i = 0; i < itemsSchema.length; i++) {
631
+ const item = itemsSchema[i]
681
632
  const tmpRes = buildValue(mergeLocation(itemsLocation, i), `obj[${i}]`)
682
633
  functionCode += `
683
634
  if (${i} < arrayLength) {
@@ -697,7 +648,7 @@ function buildArray (location) {
697
648
 
698
649
  if (schema.additionalItems) {
699
650
  functionCode += `
700
- for (let i = ${schema.items.length}; i < arrayLength; i++) {
651
+ for (let i = ${itemsSchema.length}; i < arrayLength; i++) {
701
652
  let json = JSON.stringify(obj[i])
702
653
  jsonOutput += json
703
654
  if (i < arrayLength - 1) {
@@ -768,9 +719,144 @@ function generateFuncName () {
768
719
  return 'anonymous' + genFuncNameCounter++
769
720
  }
770
721
 
722
+ function buildMultiTypeSerializer (location, input) {
723
+ const schema = location.schema
724
+ const types = schema.type.sort(t1 => t1 === 'null' ? -1 : 1)
725
+
726
+ let code = ''
727
+
728
+ const locationClone = clone(location)
729
+ types.forEach((type, index) => {
730
+ const statement = index === 0 ? 'if' : 'else if'
731
+ locationClone.schema.type = type
732
+ const nestedResult = buildSingleTypeSerializer(locationClone, input)
733
+ switch (type) {
734
+ case 'null':
735
+ code += `
736
+ ${statement} (${input} === null)
737
+ ${nestedResult}
738
+ `
739
+ break
740
+ case 'string': {
741
+ code += `
742
+ ${statement}(
743
+ typeof ${input} === "string" ||
744
+ ${input} === null ||
745
+ ${input} instanceof Date ||
746
+ ${input} instanceof RegExp ||
747
+ (
748
+ typeof ${input} === "object" &&
749
+ typeof ${input}.toString === "function" &&
750
+ ${input}.toString !== Object.prototype.toString &&
751
+ !(${input} instanceof Date)
752
+ )
753
+ )
754
+ ${nestedResult}
755
+ `
756
+ break
757
+ }
758
+ case 'array': {
759
+ code += `
760
+ ${statement}(Array.isArray(${input}))
761
+ ${nestedResult}
762
+ `
763
+ break
764
+ }
765
+ case 'integer': {
766
+ code += `
767
+ ${statement}(Number.isInteger(${input}) || ${input} === null)
768
+ ${nestedResult}
769
+ `
770
+ break
771
+ }
772
+ default: {
773
+ code += `
774
+ ${statement}(typeof ${input} === "${type}" || ${input} === null)
775
+ ${nestedResult}
776
+ `
777
+ break
778
+ }
779
+ }
780
+ })
781
+ code += `
782
+ else throw new Error(\`The value $\{JSON.stringify(${input})} does not match schema definition.\`)
783
+ `
784
+
785
+ return code
786
+ }
787
+
788
+ function buildSingleTypeSerializer (location, input) {
789
+ const schema = location.schema
790
+
791
+ switch (schema.type) {
792
+ case 'null':
793
+ return 'json += \'null\''
794
+ case 'string': {
795
+ if (schema.format === 'date-time') {
796
+ return `json += serializer.asDateTime(${input})`
797
+ } else if (schema.format === 'date') {
798
+ return `json += serializer.asDate(${input})`
799
+ } else if (schema.format === 'time') {
800
+ return `json += serializer.asTime(${input})`
801
+ } else {
802
+ return `json += serializer.asString(${input})`
803
+ }
804
+ }
805
+ case 'integer':
806
+ return `json += serializer.asInteger(${input})`
807
+ case 'number':
808
+ return `json += serializer.asNumber(${input})`
809
+ case 'boolean':
810
+ return `json += serializer.asBoolean(${input})`
811
+ case 'object': {
812
+ const funcName = buildObject(location)
813
+ return `json += ${funcName}(${input})`
814
+ }
815
+ case 'array': {
816
+ const funcName = buildArray(location)
817
+ return `json += ${funcName}(${input})`
818
+ }
819
+ case undefined:
820
+ return `json += JSON.stringify(${input})`
821
+ default:
822
+ throw new Error(`${schema.type} unsupported`)
823
+ }
824
+ }
825
+
826
+ function buildConstSerializer (location, input) {
827
+ const schema = location.schema
828
+ const type = schema.type
829
+
830
+ const hasNullType = Array.isArray(type) && type.includes('null')
831
+
832
+ let code = ''
833
+
834
+ if (hasNullType) {
835
+ code += `
836
+ if (${input} === null) {
837
+ json += 'null'
838
+ } else {
839
+ `
840
+ }
841
+
842
+ code += `json += '${JSON.stringify(schema.const)}'`
843
+
844
+ if (hasNullType) {
845
+ code += `
846
+ }
847
+ `
848
+ }
849
+
850
+ return code
851
+ }
852
+
771
853
  function buildValue (location, input) {
772
854
  let schema = location.schema
773
855
 
856
+ if (typeof schema === 'boolean') {
857
+ return `json += JSON.stringify(${input})`
858
+ }
859
+
774
860
  if (schema.$ref) {
775
861
  location = resolveRef(location, schema.$ref)
776
862
  schema = location.schema
@@ -791,185 +877,61 @@ function buildValue (location, input) {
791
877
  }
792
878
 
793
879
  const type = schema.type
794
- const nullable = schema.nullable === true
795
880
 
796
881
  let code = ''
797
- let funcName
798
882
 
799
- switch (type) {
800
- case 'null':
883
+ if (type === undefined && (schema.anyOf || schema.oneOf)) {
884
+ const type = schema.anyOf ? 'anyOf' : 'oneOf'
885
+ const anyOfLocation = mergeLocation(location, type)
886
+
887
+ for (let index = 0; index < location.schema[type].length; index++) {
888
+ const optionLocation = mergeLocation(anyOfLocation, index)
889
+ const schemaRef = optionLocation.schemaId + optionLocation.jsonPointer
890
+ const nestedResult = buildValue(optionLocation, input)
801
891
  code += `
802
- json += serializer.asNull()
892
+ ${index === 0 ? 'if' : 'else if'}(validator.validate("${schemaRef}", ${input}))
893
+ ${nestedResult}
803
894
  `
804
- break
805
- case 'string': {
806
- funcName = getStringSerializer(schema.format, nullable)
807
- code += `json += ${funcName}(${input})`
808
- break
809
895
  }
810
- case 'integer':
811
- funcName = nullable ? 'serializer.asIntegerNullable.bind(serializer)' : 'serializer.asInteger.bind(serializer)'
812
- code += `json += ${funcName}(${input})`
813
- break
814
- case 'number':
815
- funcName = nullable ? 'serializer.asNumberNullable.bind(serializer)' : 'serializer.asNumber.bind(serializer)'
816
- code += `json += ${funcName}(${input})`
817
- break
818
- case 'boolean':
819
- funcName = nullable ? 'serializer.asBooleanNullable.bind(serializer)' : 'serializer.asBoolean.bind(serializer)'
820
- code += `json += ${funcName}(${input})`
821
- break
822
- case 'object':
823
- funcName = buildObject(location)
824
- code += `json += ${funcName}(${input})`
825
- break
826
- case 'array':
827
- funcName = buildArray(location)
828
- code += `json += ${funcName}(${input})`
829
- break
830
- case undefined:
831
- if (schema.fjs_date_type) {
832
- funcName = getStringSerializer(schema.fjs_date_type, nullable)
833
- code += `json += ${funcName}(${input})`
834
- break
835
- } else if (schema.anyOf || schema.oneOf) {
836
- // beware: dereferenceOfRefs has side effects and changes schema.anyOf
837
- const type = schema.anyOf ? 'anyOf' : 'oneOf'
838
- const anyOfLocation = mergeLocation(location, type)
839
-
840
- for (let index = 0; index < location.schema[type].length; index++) {
841
- const optionLocation = mergeLocation(anyOfLocation, index)
842
- const schemaRef = optionLocation.schemaId + optionLocation.jsonPointer
843
- const nestedResult = buildValue(optionLocation, input)
844
- code += `
845
- ${index === 0 ? 'if' : 'else if'}(ajv.validate("${schemaRef}", ${input}))
846
- ${nestedResult}
847
- `
848
- }
849
-
850
- code += `
851
- else throw new Error(\`The value $\{JSON.stringify(${input})} does not match schema definition.\`)
852
- `
853
- } else if (isEmpty(schema)) {
854
- code += `
855
- json += JSON.stringify(${input})
856
- `
857
- } else if ('const' in schema) {
858
- code += `
859
- if(ajv.validate(${JSON.stringify(schema)}, ${input}))
860
- json += '${JSON.stringify(schema.const)}'
861
- else
862
- throw new Error(\`Item $\{JSON.stringify(${input})} does not match schema definition.\`)
863
- `
864
- } else if (schema.type === undefined) {
865
- code += `
866
- json += JSON.stringify(${input})
867
- `
868
- } else {
869
- throw new Error(`${schema.type} unsupported`)
870
- }
871
- break
872
- default:
873
- if (Array.isArray(type)) {
874
- let sortedTypes = type
875
- const nullable = schema.nullable === true || type.includes('null')
876
-
877
- if (nullable) {
878
- sortedTypes = sortedTypes.filter(type => type !== 'null')
879
- code += `
880
- if (${input} === null) {
881
- json += null
882
- } else {`
883
- }
884
896
 
885
- const locationClone = clone(location)
886
- sortedTypes.forEach((type, index) => {
887
- const statement = index === 0 ? 'if' : 'else if'
888
- locationClone.schema.type = type
889
- const nestedResult = buildValue(locationClone, input)
890
- switch (type) {
891
- case 'string': {
892
- code += `
893
- ${statement}(${input} === null || typeof ${input} === "${type}" || ${input} instanceof Date || ${input} instanceof RegExp || (typeof ${input} === "object" && Object.hasOwnProperty.call(${input}, "toString")))
894
- ${nestedResult}
895
- `
896
- break
897
- }
898
- case 'array': {
899
- code += `
900
- ${statement}(Array.isArray(${input}))
901
- ${nestedResult}
902
- `
903
- break
904
- }
905
- case 'integer': {
906
- code += `
907
- ${statement}(Number.isInteger(${input}) || ${input} === null)
908
- ${nestedResult}
909
- `
910
- break
911
- }
912
- default: {
913
- code += `
914
- ${statement}(typeof ${input} === "${type}" || ${input} === null)
915
- ${nestedResult}
916
- `
917
- break
918
- }
919
- }
920
- })
921
- code += `
922
- else throw new Error(\`The value $\{JSON.stringify(${input})} does not match schema definition.\`)
923
- `
897
+ code += `
898
+ else throw new Error(\`The value $\{JSON.stringify(${input})} does not match schema definition.\`)
899
+ `
900
+ return code
901
+ }
924
902
 
925
- if (nullable) {
926
- code += `
927
- }
928
- `
929
- }
903
+ const nullable = schema.nullable === true
904
+ if (nullable) {
905
+ code += `
906
+ if (${input} === null) {
907
+ json += 'null'
930
908
  } else {
931
- throw new Error(`${type} unsupported`)
932
- }
909
+ `
933
910
  }
934
911
 
935
- return code
936
- }
937
-
938
- // Ajv does not support js date format. In order to properly validate objects containing a date,
939
- // it needs to replace all occurrences of the string date format with a custom keyword fjs_date_type.
940
- // (see https://github.com/fastify/fast-json-stringify/pull/441)
941
- function extendDateTimeType (schema) {
942
- if (schema === null) return
943
-
944
- if (schema.type === 'string' && ['date-time', 'date', 'time'].includes(schema.format)) {
945
- schema.fjs_date_type = schema.format
946
- delete schema.type
947
- delete schema.format
948
- }
949
- for (const property in schema) {
950
- if (typeof schema[property] === 'object') {
951
- extendDateTimeType(schema[property])
952
- }
912
+ if (schema.const !== undefined) {
913
+ code += buildConstSerializer(location, input)
914
+ } else if (Array.isArray(type)) {
915
+ code += buildMultiTypeSerializer(location, input)
916
+ } else {
917
+ code += buildSingleTypeSerializer(location, input)
953
918
  }
954
- }
955
919
 
956
- function isEmpty (schema) {
957
- // eslint-disable-next-line
958
- for (var key in schema) {
959
- if (schema.hasOwnProperty(key) && schema[key] !== undefined) {
960
- return false
961
- }
920
+ if (nullable) {
921
+ code += `
922
+ }
923
+ `
962
924
  }
963
- return true
925
+
926
+ return code
964
927
  }
965
928
 
966
929
  module.exports = build
967
930
 
968
931
  module.exports.validLargeArrayMechanisms = validLargeArrayMechanisms
969
932
 
970
- module.exports.restore = function ({ code, ajv }) {
971
- const serializer = new Serializer()
933
+ module.exports.restore = function ({ code, validator, serializer }) {
972
934
  // eslint-disable-next-line
973
- return (Function.apply(null, ['ajv', 'serializer', code])
974
- .apply(null, [ajv, serializer]))
935
+ return (Function.apply(null, ['validator', 'serializer', code])
936
+ .apply(null, [validator, serializer]))
975
937
  }