@@ -298,59 +298,96 @@ function buildExtraObjectPropertiesSerializer (context, location) {
298298}
299299
300300function buildInnerObject ( context , location ) {
301+ let code = ''
301302 const schema = location . schema
302303 const required = schema . required || [ ]
303304
304- let code = ''
305-
306305 const propertiesLocation = location . getPropertyLocation ( 'properties' )
307- Object . keys ( schema . properties || { } ) . forEach ( ( key ) => {
308- let propertyLocation = propertiesLocation . getPropertyLocation ( key )
309- if ( propertyLocation . schema . $ref ) {
310- propertyLocation = resolveRef ( context , location , propertyLocation . schema . $ref )
306+
307+ const requiredWithDefault = [ ]
308+ const requiredWithoutDefault = [ ]
309+ if ( schema . properties ) {
310+ for ( const key of Object . keys ( schema . properties ) ) {
311+ if ( required . indexOf ( key ) === - 1 ) {
312+ continue
313+ }
314+ let propertyLocation = propertiesLocation . getPropertyLocation ( key )
315+ if ( propertyLocation . schema . $ref ) {
316+ propertyLocation = resolveRef ( context , location , propertyLocation . schema . $ref )
317+ }
318+
319+ const sanitizedKey = JSON . stringify ( key )
320+
321+ // Using obj['key'] !== undefined instead of obj.hasOwnProperty(prop) for perf reasons,
322+ // see https://github.com/mcollina/fast-json-stringify/pull/3 for discussion.
323+ const defaultValue = propertyLocation . schema . default
324+ if ( defaultValue === undefined ) {
325+ code += `if (obj[${ sanitizedKey } ] === undefined) throw new Error('${ sanitizedKey } is required!')\n`
326+ requiredWithoutDefault . push ( key )
327+ }
328+ requiredWithDefault . push ( key )
311329 }
330+ }
312331
313- const sanitized = JSON . stringify ( key )
332+ // handle extraneous required fields
333+ for ( const requiredProperty of required ) {
334+ if ( requiredWithDefault . indexOf ( requiredProperty ) !== - 1 ) continue
335+ code += `if (obj['${ requiredProperty } '] === undefined) throw new Error('"${ requiredProperty } " is required!')\n`
336+ }
314337
315- // Using obj['key'] !== undefined instead of obj.hasOwnProperty(prop) for perf reasons,
316- // see https://github.com/mcollina/fast-json-stringify/pull/3 for discussion.
338+ code += `
339+ let addComma = false
340+ let json = '${ context . wrapObjects ? '{' : '' } '
341+ `
342+ const wrapObjects = context . wrapObjects
343+ context . wrapObjects = true
317344
318- code += `
319- if (obj[${ sanitized } ] !== undefined) {
320- ${ addComma }
321- json += ${ JSON . stringify ( sanitized + ':' ) }
322- `
345+ if ( schema . properties ) {
346+ for ( const key of Object . keys ( schema . properties ) ) {
347+ let propertyLocation = propertiesLocation . getPropertyLocation ( key )
348+ if ( propertyLocation . schema . $ref ) {
349+ propertyLocation = resolveRef ( context , location , propertyLocation . schema . $ref )
350+ }
323351
324- code += buildValue ( context , propertyLocation , `obj[ ${ sanitized } ]` )
352+ const sanitizedKey = JSON . stringify ( key )
325353
326- const defaultValue = propertyLocation . schema . default
327- if ( defaultValue !== undefined ) {
328- code += `
329- } else {
354+ if ( requiredWithoutDefault . indexOf ( key ) !== - 1 ) {
355+ code += `
330356 ${ addComma }
331- json += ${ JSON . stringify ( sanitized + ':' + JSON . stringify ( defaultValue ) ) }
357+ json += ${ JSON . stringify ( sanitizedKey + ':' ) }
358+ ${ buildValue ( context , propertyLocation , `obj[${ sanitizedKey } ]` ) }
332359 `
333- } else if ( required . includes ( key ) ) {
334- code += `
335360 } else {
336- throw new Error('${ sanitized } is required!')
337- `
338- }
339-
340- code += `
361+ // Using obj['key'] !== undefined instead of obj.hasOwnProperty(prop) for perf reasons,
362+ // see https://github.com/mcollina/fast-json-stringify/pull/3 for discussion.
363+ code += `
364+ if (obj[${ sanitizedKey } ] !== undefined) {
365+ ${ addComma }
366+ json += ${ JSON . stringify ( sanitizedKey + ':' ) }
367+ ${ buildValue ( context , propertyLocation , `obj[${ sanitizedKey } ]` ) }
368+ }
369+ `
370+ const defaultValue = propertyLocation . schema . default
371+ if ( defaultValue !== undefined ) {
372+ code += `
373+ else {
374+ ${ addComma }
375+ json += ${ JSON . stringify ( sanitizedKey + ':' + JSON . stringify ( defaultValue ) ) }
376+ }
377+ `
378+ }
341379 }
342- `
343- } )
344-
345- for ( const requiredProperty of required ) {
346- if ( schema . properties && schema . properties [ requiredProperty ] !== undefined ) continue
347- code += `if (obj['${ requiredProperty } '] === undefined) throw new Error('"${ requiredProperty } " is required!')\n`
380+ }
348381 }
349382
350383 if ( schema . patternProperties || schema . additionalProperties ) {
351384 code += buildExtraObjectPropertiesSerializer ( context , location )
352385 }
353386
387+ context . wrapObjects = wrapObjects
388+ code += `
389+ return json${ context . wrapObjects ? ' + \'}\'' : '' }
390+ `
354391 return code
355392}
356393
@@ -505,22 +542,13 @@ function buildObject (context, location) {
505542 }
506543
507544 let functionCode = `
508- function ${ functionName } (input) {
509- // ${ schemaRef }
510545 `
511546
512547 functionCode += `
548+ // ${ schemaRef }
549+ function ${ functionName } (input) {
513550 const obj = ${ toJSON ( 'input' ) }
514- let json = '${ context . wrapObjects ? '{' : '' } '
515- let addComma = false
516- `
517-
518- const wrapObjects = context . wrapObjects
519- context . wrapObjects = true
520- functionCode += buildInnerObject ( context , location )
521- context . wrapObjects = wrapObjects
522- functionCode += `
523- return json${ context . wrapObjects ? ' + \'}\'' : '' }
551+ ${ buildInnerObject ( context , location ) }
524552 }
525553 `
526554
0 commit comments