diff --git a/index.js b/index.js index a2d07dcf..b8a0d61e 100644 --- a/index.js +++ b/index.js @@ -76,6 +76,7 @@ function build (schema, options) { functionsCounter: 0, functionsNamesBySchema: new Map(), options, + wrapObjects: true, refResolver: new RefResolver(), rootSchemaId: schema.$id || randomUUID(), validatorSchemasIds: new Set() @@ -510,13 +511,16 @@ function buildObject (context, location) { functionCode += ` const obj = ${toJSON('input')} - let json = '{' + let json = '${context.wrapObjects ? '{' : ''}' let addComma = false ` + const wrapObjects = context.wrapObjects + context.wrapObjects = true functionCode += buildInnerObject(context, location) + context.wrapObjects = wrapObjects functionCode += ` - return json + '}' + return json${context.wrapObjects ? ' + \'}\'' : ''} } ` @@ -832,9 +836,19 @@ function buildValue (context, location, input) { let code = '' - if (type === undefined && (schema.anyOf || schema.oneOf)) { + if ((type === undefined || type === 'object') && (schema.anyOf || schema.oneOf)) { context.validatorSchemasIds.add(location.getSchemaId()) + if (schema.type === 'object') { + context.wrapObjects = false + const funcName = buildObject(context, location) + code += ` + json += '{' + json += ${funcName}(${input}) + json += ',' + ` + } + const type = schema.anyOf ? 'anyOf' : 'oneOf' const anyOfLocation = location.getPropertyLocation(type) @@ -856,6 +870,12 @@ function buildValue (context, location, input) { code += ` else throw new TypeError(\`The value of '${schemaRef}' does not match schema definition.\`) ` + if (schema.type === 'object') { + code += ` + json += '}' + ` + context.wrapObjects = true + } return code } diff --git a/test/allof.test.js b/test/allof.test.js index 942725d5..d0b8b74f 100644 --- a/test/allof.test.js +++ b/test/allof.test.js @@ -220,6 +220,75 @@ test('object with nested allOfs', (t) => { t.equal(value, '{"id1":1,"id2":2,"id3":3}') }) +test('object with anyOf nested inside allOf', (t) => { + t.plan(1) + + const schema = { + title: 'object with anyOf nested inside allOf', + type: 'object', + allOf: [ + { + required: ['id1', 'obj'], + type: 'object', + properties: { + id1: { + type: 'integer' + }, + obj: { + type: 'object', + properties: { + nested: { type: 'string' } + } + } + } + }, + { + anyOf: [ + { + type: 'object', + properties: { + id2: { type: 'string' } + }, + required: ['id2'] + }, + { + type: 'object', + properties: { + id3: { + type: 'integer' + }, + nestedObj: { + type: 'object', + properties: { + nested: { type: 'string' } + } + } + }, + required: ['id3'] + }, + { + type: 'object', + properties: { + id4: { type: 'integer' } + }, + required: ['id4'] + } + ] + } + ] + } + + const stringify = build(schema) + const value = stringify({ + id1: 1, + id3: 3, + id4: 4, // extra prop shouldn't be in result + obj: { nested: 'yes' }, + nestedObj: { nested: 'yes' } + }) + t.equal(value, '{"id1":1,"obj":{"nested":"yes"},"id3":3,"nestedObj":{"nested":"yes"}}') +}) + test('object with $ref in allOf', (t) => { t.plan(1)