Skip to content

Commit 66af8c9

Browse files
refactor: refactor and optimize extra properties serializer (#531)
* refactor: refactor and optimize extra properties serializer * refactor: remove duplicate ref resolving for pattern/additional properties
1 parent 13445f7 commit 66af8c9

File tree

1 file changed

+50
-77
lines changed

1 file changed

+50
-77
lines changed

index.js

Lines changed: 50 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -238,92 +238,72 @@ function inferTypeByKeyword (schema) {
238238
return schema.type
239239
}
240240

241-
function addPatternProperties (location) {
241+
function buildExtraObjectPropertiesSerializer (location) {
242242
const schema = location.schema
243-
const pp = schema.patternProperties
243+
const propertiesKeys = Object.keys(schema.properties || {})
244+
244245
let code = `
245-
var properties = ${JSON.stringify(schema.properties)} || {}
246-
var keys = Object.keys(obj)
247-
for (var i = 0; i < keys.length; i++) {
248-
if (properties[keys[i]]) continue
246+
const propertiesKeys = ${JSON.stringify(propertiesKeys)}
247+
for (const [key, value] of Object.entries(obj)) {
248+
if (
249+
propertiesKeys.includes(key) ||
250+
value === undefined ||
251+
typeof value === 'function' ||
252+
typeof value === 'symbol'
253+
) continue
249254
`
250255

251256
const patternPropertiesLocation = mergeLocation(location, 'patternProperties')
252-
Object.keys(pp).forEach((regex) => {
253-
let ppLocation = mergeLocation(patternPropertiesLocation, regex)
254-
if (pp[regex].$ref) {
255-
ppLocation = resolveRef(ppLocation, pp[regex].$ref)
256-
pp[regex] = ppLocation.schema
257-
}
257+
const patternPropertiesSchema = patternPropertiesLocation.schema
258258

259-
try {
260-
RegExp(regex)
261-
} catch (err) {
262-
throw new Error(`${err.message}. Found at ${regex} matching ${JSON.stringify(pp[regex])}`)
263-
}
259+
if (patternPropertiesSchema !== undefined) {
260+
for (const propertyKey in patternPropertiesSchema) {
261+
const propertyLocation = mergeLocation(patternPropertiesLocation, propertyKey)
264262

265-
const valueCode = buildValue(ppLocation, 'obj[keys[i]]')
266-
code += `
267-
if (/${regex.replace(/\\*\//g, '\\/')}/.test(keys[i])) {
268-
${addComma}
269-
json += serializer.asString(keys[i]) + ':'
270-
${valueCode}
271-
continue
263+
try {
264+
RegExp(propertyKey)
265+
} catch (err) {
266+
const jsonPointer = propertyLocation.schema + propertyLocation.jsonPointer
267+
throw new Error(`${err.message}. Invalid pattern property regexp key ${propertyKey} at ${jsonPointer}`)
272268
}
273-
`
274-
})
275-
if (schema.additionalProperties) {
276-
code += additionalProperty(location)
277-
}
278269

279-
code += `
280-
}
281-
`
282-
return code
283-
}
284-
285-
function additionalProperty (location) {
286-
const ap = location.schema.additionalProperties
287-
let code = ''
288-
if (ap === true) {
289-
code += `
290-
if (obj[keys[i]] !== undefined && typeof obj[keys[i]] !== 'function' && typeof obj[keys[i]] !== 'symbol') {
270+
code += `
271+
if (/${propertyKey.replace(/\\*\//g, '\\/')}/.test(key)) {
291272
${addComma}
292-
json += serializer.asString(keys[i]) + ':' + JSON.stringify(obj[keys[i]])
273+
json += serializer.asString(key) + ':'
274+
${buildValue(propertyLocation, 'value')}
275+
continue
293276
}
294-
`
295-
296-
return code
277+
`
278+
}
297279
}
298280

299-
let apLocation = mergeLocation(location, 'additionalProperties')
300-
if (apLocation.schema.$ref) {
301-
apLocation = resolveRef(apLocation, apLocation.schema.$ref)
302-
}
281+
const additionalPropertiesLocation = mergeLocation(location, 'additionalProperties')
282+
const additionalPropertiesSchema = additionalPropertiesLocation.schema
303283

304-
const valueCode = buildValue(apLocation, 'obj[keys[i]]')
284+
if (additionalPropertiesSchema !== undefined) {
285+
if (additionalPropertiesSchema === true) {
286+
code += `
287+
${addComma}
288+
json += serializer.asString(key) + ':' + JSON.stringify(value)
289+
`
290+
} else {
291+
const propertyLocation = mergeLocation(location, 'additionalProperties')
292+
code += `
293+
${addComma}
294+
json += serializer.asString(key) + ':'
295+
${buildValue(propertyLocation, 'value')}
296+
`
297+
}
298+
}
305299

306300
code += `
307-
${addComma}
308-
json += serializer.asString(keys[i]) + ':'
309-
${valueCode}
301+
}
310302
`
311-
312303
return code
313304
}
314305

315-
function addAdditionalProperties (location) {
316-
return `
317-
var properties = ${JSON.stringify(location.schema.properties)} || {}
318-
var keys = Object.keys(obj)
319-
for (var i = 0; i < keys.length; i++) {
320-
if (properties[keys[i]]) continue
321-
${additionalProperty(location)}
322-
}
323-
`
324-
}
325-
326-
function buildCode (location) {
306+
function buildInnerObject (location) {
327307
if (location.schema.$ref) {
328308
location = resolveRef(location, location.schema.$ref)
329309
}
@@ -378,6 +358,10 @@ function buildCode (location) {
378358
code += `if (obj['${requiredProperty}'] === undefined) throw new Error('"${requiredProperty}" is required!')\n`
379359
}
380360

361+
if (schema.patternProperties || schema.additionalProperties) {
362+
code += buildExtraObjectPropertiesSerializer(location)
363+
}
364+
381365
return code
382366
}
383367

@@ -481,17 +465,6 @@ function mergeAllOfSchema (location, schema, mergedSchema) {
481465
location.jsonPointer = '#'
482466
}
483467

484-
function buildInnerObject (location) {
485-
const schema = location.schema
486-
let code = buildCode(location)
487-
if (schema.patternProperties) {
488-
code += addPatternProperties(location)
489-
} else if (schema.additionalProperties && !schema.patternProperties) {
490-
code += addAdditionalProperties(location)
491-
}
492-
return code
493-
}
494-
495468
function addIfThenElse (location, input) {
496469
location.isValidated = true
497470
validatorSchemasIds.add(location.schemaId)

0 commit comments

Comments
 (0)