@@ -549,13 +549,6 @@ function buildObject (location) {
549549 function ${ functionName } (input) {
550550 // ${ schemaId + location . jsonPointer }
551551 `
552- if ( schema . nullable ) {
553- functionCode += `
554- if (input === null) {
555- return 'null';
556- }
557- `
558- }
559552
560553 functionCode += `
561554 var obj = ${ toJSON ( 'input' ) }
@@ -604,14 +597,6 @@ function buildArray (location) {
604597 // ${ schemaId + location . jsonPointer }
605598 `
606599
607- if ( schema . nullable ) {
608- functionCode += `
609- if (obj === null) {
610- return 'null';
611- }
612- `
613- }
614-
615600 functionCode += `
616601 if (!Array.isArray(obj)) {
617602 throw new TypeError(\`The value '$\{obj}' does not match schema definition.\`)
@@ -732,6 +717,137 @@ function generateFuncName () {
732717 return 'anonymous' + genFuncNameCounter ++
733718}
734719
720+ function buildMultiTypeSerializer ( location , input ) {
721+ const schema = location . schema
722+ const types = schema . type . sort ( t1 => t1 === 'null' ? - 1 : 1 )
723+
724+ let code = ''
725+
726+ const locationClone = clone ( location )
727+ types . forEach ( ( type , index ) => {
728+ const statement = index === 0 ? 'if' : 'else if'
729+ locationClone . schema . type = type
730+ const nestedResult = buildSingleTypeSerializer ( locationClone , input )
731+ switch ( type ) {
732+ case 'null' :
733+ code += `
734+ ${ statement } (${ input } === null)
735+ ${ nestedResult }
736+ `
737+ break
738+ case 'string' : {
739+ code += `
740+ ${ statement } (
741+ typeof ${ input } === "string" ||
742+ ${ input } === null ||
743+ ${ input } instanceof Date ||
744+ ${ input } instanceof RegExp ||
745+ (
746+ typeof ${ input } === "object" &&
747+ typeof ${ input } .toString === "function" &&
748+ ${ input } .toString !== Object.prototype.toString &&
749+ !(${ input } instanceof Date)
750+ )
751+ )
752+ ${ nestedResult }
753+ `
754+ break
755+ }
756+ case 'array' : {
757+ code += `
758+ ${ statement } (Array.isArray(${ input } ))
759+ ${ nestedResult }
760+ `
761+ break
762+ }
763+ case 'integer' : {
764+ code += `
765+ ${ statement } (Number.isInteger(${ input } ) || ${ input } === null)
766+ ${ nestedResult }
767+ `
768+ break
769+ }
770+ default : {
771+ code += `
772+ ${ statement } (typeof ${ input } === "${ type } " || ${ input } === null)
773+ ${ nestedResult }
774+ `
775+ break
776+ }
777+ }
778+ } )
779+ code += `
780+ else throw new Error(\`The value $\{JSON.stringify(${ input } )} does not match schema definition.\`)
781+ `
782+
783+ return code
784+ }
785+
786+ function buildSingleTypeSerializer ( location , input ) {
787+ const schema = location . schema
788+
789+ switch ( schema . type ) {
790+ case 'null' :
791+ return 'json += \'null\''
792+ case 'string' : {
793+ if ( schema . format === 'date-time' ) {
794+ return `json += serializer.asDateTime(${ input } )`
795+ } else if ( schema . format === 'date' ) {
796+ return `json += serializer.asDate(${ input } )`
797+ } else if ( schema . format === 'time' ) {
798+ return `json += serializer.asTime(${ input } )`
799+ } else {
800+ return `json += serializer.asString(${ input } )`
801+ }
802+ }
803+ case 'integer' :
804+ return `json += serializer.asInteger(${ input } )`
805+ case 'number' :
806+ return `json += serializer.asNumber(${ input } )`
807+ case 'boolean' :
808+ return `json += serializer.asBoolean(${ input } )`
809+ case 'object' : {
810+ const funcName = buildObject ( location )
811+ return `json += ${ funcName } (${ input } )`
812+ }
813+ case 'array' : {
814+ const funcName = buildArray ( location )
815+ return `json += ${ funcName } (${ input } )`
816+ }
817+ case undefined :
818+ return `json += JSON.stringify(${ input } )`
819+ default :
820+ throw new Error ( `${ schema . type } unsupported` )
821+ }
822+ }
823+
824+ function buildConstSerializer ( location , input ) {
825+ const schema = location . schema
826+ const type = schema . type
827+
828+ const hasNullType = Array . isArray ( type ) && type . includes ( 'null' )
829+
830+ let code = ''
831+
832+ if ( hasNullType ) {
833+ code += `
834+ if (${ input } === null) {
835+ json += 'null'
836+ } else {
837+ `
838+ }
839+
840+ code += `json += '${ JSON . stringify ( schema . const ) } '`
841+
842+ if ( hasNullType ) {
843+ code += `
844+ }
845+ `
846+ }
847+
848+ return code
849+ }
850+
735851function buildValue ( location , input ) {
736852 let schema = location . schema
737853
@@ -759,163 +875,50 @@ function buildValue (location, input) {
759875 }
760876
761877 const type = schema . type
762- const nullable = schema . nullable === true || ( Array . isArray ( type ) && type . includes ( 'null' ) )
763878
764879 let code = ''
765- let funcName
766880
767- if ( 'const' in schema ) {
768- if ( nullable ) {
881+ if ( type === undefined && ( schema . anyOf || schema . oneOf ) ) {
882+ const type = schema . anyOf ? 'anyOf' : 'oneOf'
883+ const anyOfLocation = mergeLocation ( location , type )
884+
885+ for ( let index = 0 ; index < location . schema [ type ] . length ; index ++ ) {
886+ const optionLocation = mergeLocation ( anyOfLocation , index )
887+ const schemaRef = optionLocation . schemaId + optionLocation . jsonPointer
888+ const nestedResult = buildValue ( optionLocation , input )
769889 code += `
770- json += ${ input } === null ? 'null' : '${ JSON . stringify ( schema . const ) } '
890+ ${ index === 0 ? 'if' : 'else if' } (validator.validate("${ schemaRef } ", ${ input } ))
891+ ${ nestedResult }
771892 `
772- return code
773893 }
774- code += `json += '${ JSON . stringify ( schema . const ) } '`
894+
895+ code += `
896+ else throw new Error(\`The value $\{JSON.stringify(${ input } )} does not match schema definition.\`)
897+ `
775898 return code
776899 }
777900
778- switch ( type ) {
779- case 'null' :
780- code += 'json += serializer.asNull()'
781- break
782- case 'string' : {
783- if ( schema . format === 'date-time' ) {
784- funcName = nullable ? 'serializer.asDateTimeNullable.bind(serializer)' : 'serializer.asDateTime.bind(serializer)'
785- } else if ( schema . format === 'date' ) {
786- funcName = nullable ? 'serializer.asDateNullable.bind(serializer)' : 'serializer.asDate.bind(serializer)'
787- } else if ( schema . format === 'time' ) {
788- funcName = nullable ? 'serializer.asTimeNullable.bind(serializer)' : 'serializer.asTime.bind(serializer)'
789- } else {
790- funcName = nullable ? 'serializer.asStringNullable.bind(serializer)' : 'serializer.asString.bind(serializer)'
791- }
792- code += `json += ${ funcName } (${ input } )`
793- break
794- }
795- case 'integer' :
796- funcName = nullable ? 'serializer.asIntegerNullable.bind(serializer)' : 'serializer.asInteger.bind(serializer)'
797- code += `json += ${ funcName } (${ input } )`
798- break
799- case 'number' :
800- funcName = nullable ? 'serializer.asNumberNullable.bind(serializer)' : 'serializer.asNumber.bind(serializer)'
801- code += `json += ${ funcName } (${ input } )`
802- break
803- case 'boolean' :
804- funcName = nullable ? 'serializer.asBooleanNullable.bind(serializer)' : 'serializer.asBoolean.bind(serializer)'
805- code += `json += ${ funcName } (${ input } )`
806- break
807- case 'object' :
808- funcName = buildObject ( location )
809- code += `json += ${ funcName } (${ input } )`
810- break
811- case 'array' :
812- funcName = buildArray ( location )
813- code += `json += ${ funcName } (${ input } )`
814- break
815- case undefined :
816- if ( schema . anyOf || schema . oneOf ) {
817- // beware: dereferenceOfRefs has side effects and changes schema.anyOf
818- const type = schema . anyOf ? 'anyOf' : 'oneOf'
819- const anyOfLocation = mergeLocation ( location , type )
820-
821- for ( let index = 0 ; index < location . schema [ type ] . length ; index ++ ) {
822- const optionLocation = mergeLocation ( anyOfLocation , index )
823- const schemaRef = optionLocation . schemaId + optionLocation . jsonPointer
824- const nestedResult = buildValue ( optionLocation , input )
825- code += `
826- ${ index === 0 ? 'if' : 'else if' } (validator.validate("${ schemaRef } ", ${ input } ))
827- ${ nestedResult }
828- `
829- }
830-
831- code += `
832- else throw new Error(\`The value $\{JSON.stringify(${ input } )} does not match schema definition.\`)
833- `
901+ const nullable = schema . nullable === true
902+ if ( nullable ) {
903+ code += `
904+ if (${ input } === null) {
905+ json += 'null'
834906 } else {
835- code += `
836- json += JSON.stringify(${ input } )
837- `
838- }
839- break
840- default :
841- if ( Array . isArray ( type ) ) {
842- let sortedTypes = type
843- const nullable = schema . nullable === true || type . includes ( 'null' )
844-
845- if ( nullable ) {
846- sortedTypes = sortedTypes . filter ( type => type !== 'null' )
847- code += `
848- if (${ input } === null) {
849- json += null
850- } else {`
851- }
907+ `
908+ }
852909
853- const locationClone = clone ( location )
854- sortedTypes . forEach ( ( type , index ) => {
855- const statement = index === 0 ? 'if' : 'else if'
856- locationClone . schema . type = type
857- const nestedResult = buildValue ( locationClone , input )
858- switch ( type ) {
859- case 'string' : {
860- code += `
861- ${ statement } (
862- typeof ${ input } === "string" ||
863- ${ input } === null ||
864- ${ input } instanceof Date ||
865- ${ input } instanceof RegExp ||
866- (
867- typeof ${ input } === "object" &&
868- typeof ${ input } .toString === "function" &&
869- ${ input } .toString !== Object.prototype.toString &&
870- !(${ input } instanceof Date)
871- )
872- )
873- ${ nestedResult }
874- `
875- break
876- }
877- case 'array' : {
878- code += `
879- ${ statement } (Array.isArray(${ input } ))
880- ${ nestedResult }
881- `
882- break
883- }
884- case 'integer' : {
885- code += `
886- ${ statement } (Number.isInteger(${ input } ) || ${ input } === null)
887- ${ nestedResult }
888- `
889- break
890- }
891- case 'object' : {
892- code += `
893- ${ statement } (typeof ${ input } === "object" || ${ input } === null)
894- ${ nestedResult }
895- `
896- break
897- }
898- default : {
899- code += `
900- ${ statement } (typeof ${ input } === "${ type } " || ${ input } === null)
901- ${ nestedResult }
902- `
903- break
904- }
905- }
906- } )
907- code += `
908- else throw new Error(\`The value $\{JSON.stringify(${ input } )} does not match schema definition.\`)
909- `
910+ if ( schema . const !== undefined ) {
911+ code += buildConstSerializer ( location , input )
912+ } else if ( Array . isArray ( type ) ) {
913+ code += buildMultiTypeSerializer ( location , input )
914+ } else {
915+ code += buildSingleTypeSerializer ( location , input )
916+ }
910917
911- if ( nullable ) {
912- code += `
913- }
914- `
915- }
916- } else {
917- throw new Error ( `${ type } unsupported` )
918+ if ( nullable ) {
919+ code += `
918920 }
921+ `
919922 }
920923
921924 return code
0 commit comments