From dd8cc10bb5b6c60150c6424c9be2db74da62261d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ro=C5=BCek?= Date: Wed, 8 May 2019 23:30:33 +0200 Subject: [PATCH] fix: array of objects with properties --- src/__fixtures__/array-of-objects.json | 21 +++++ .../__snapshots__/renderSchema.spec.ts.snap | 77 +++++++++++++++++++ src/utils/__tests__/renderSchema.spec.ts | 26 ++++--- src/utils/renderSchema.ts | 24 +++--- src/utils/walk.ts | 16 +++- 5 files changed, 138 insertions(+), 26 deletions(-) create mode 100644 src/__fixtures__/array-of-objects.json diff --git a/src/__fixtures__/array-of-objects.json b/src/__fixtures__/array-of-objects.json new file mode 100644 index 00000000..b928df8a --- /dev/null +++ b/src/__fixtures__/array-of-objects.json @@ -0,0 +1,21 @@ +{ + "type": "object", + "xml": { + "name": "Pet" + }, + "properties": { + "propertyIsArrayOfObjects": { + "type": [ + "array" + ], + "items": { + "type": "object", + "properties": { + "ArrayObjectProperty": { + "type": "string" + } + } + } + } + } +} diff --git a/src/utils/__tests__/__snapshots__/renderSchema.spec.ts.snap b/src/utils/__tests__/__snapshots__/renderSchema.spec.ts.snap index 9568ecee..cc0608c3 100644 --- a/src/utils/__tests__/__snapshots__/renderSchema.spec.ts.snap +++ b/src/utils/__tests__/__snapshots__/renderSchema.spec.ts.snap @@ -1,5 +1,82 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`renderSchema util should match array-of-objects.json 1`] = ` +Array [ + Object { + "canHaveChildren": true, + "id": "random-id", + "level": 0, + "metadata": Object { + "additionalProperties": undefined, + "annotations": Object {}, + "enum": undefined, + "id": "random-id", + "path": Array [], + "patternProperties": undefined, + "properties": Object { + "propertyIsArrayOfObjects": Object { + "items": Object { + "properties": Object { + "ArrayObjectProperty": Object { + "type": "string", + }, + }, + "type": "object", + }, + "type": Array [ + "array", + ], + }, + }, + "type": "object", + "validations": Object {}, + }, + "name": "", + }, + Object { + "id": "random-id", + "level": 1, + "metadata": Object { + "additionalItems": undefined, + "annotations": Object {}, + "enum": undefined, + "id": "random-id", + "items": undefined, + "name": "propertyIsArrayOfObjects", + "path": Array [ + "properties", + "propertyIsArrayOfObjects", + ], + "required": false, + "subtype": "object", + "type": "array", + "validations": Object {}, + }, + "name": "", + }, + Object { + "id": "random-id", + "level": 3, + "metadata": Object { + "annotations": Object {}, + "enum": undefined, + "id": "random-id", + "name": "ArrayObjectProperty", + "path": Array [ + "properties", + "propertyIsArrayOfObjects", + "items", + "ArrayObjectProperty", + ], + "required": false, + "type": "string", + "validations": Object {}, + }, + "name": "", + }, +] +`; + exports[`renderSchema util should match combiner-schema.json 1`] = ` Array [ Object { diff --git a/src/utils/__tests__/renderSchema.spec.ts b/src/utils/__tests__/renderSchema.spec.ts index b1ee5426..6042afce 100644 --- a/src/utils/__tests__/renderSchema.spec.ts +++ b/src/utils/__tests__/renderSchema.spec.ts @@ -9,17 +9,19 @@ jest.mock('../assignId', () => ({ })); describe('renderSchema util', () => { - it.each([['default-schema.json', ''], ['ref/original.json', 'ref/resolved.json'], ['combiner-schema.json', '']])( - 'should match %s', - (schema, dereferenced) => { - expect( - Array.from( - renderSchema( - JSON.parse(fs.readFileSync(path.resolve(BASE_PATH, schema), 'utf-8')), - dereferenced ? JSON.parse(fs.readFileSync(path.resolve(BASE_PATH, dereferenced), 'utf-8')) : undefined - ) + it.each([ + ['default-schema.json', ''], + ['ref/original.json', 'ref/resolved.json'], + ['combiner-schema.json', ''], + ['array-of-objects.json', ''], + ])('should match %s', (schema, dereferenced) => { + expect( + Array.from( + renderSchema( + JSON.parse(fs.readFileSync(path.resolve(BASE_PATH, schema), 'utf-8')), + dereferenced ? JSON.parse(fs.readFileSync(path.resolve(BASE_PATH, dereferenced), 'utf-8')) : undefined ) - ).toMatchSnapshot(); - } - ); + ) + ).toMatchSnapshot(); + }); }); diff --git a/src/utils/renderSchema.ts b/src/utils/renderSchema.ts index 6a60c1e7..1756a823 100644 --- a/src/utils/renderSchema.ts +++ b/src/utils/renderSchema.ts @@ -103,22 +103,26 @@ export const renderSchema: Walker = function*(schema, dereferencedSchema, level (node as IArrayNode).additionalItems && { additional: (node as IArrayNode).additionalItems }), }, } as SchemaTreeListNode; - if (Array.isArray(schema.items)) { for (const [i, property] of schema.items.entries()) { yield* renderSchema(property, dereferencedSchema, level + 1, { path: [...path, 'items', i], }); } - } else if (meta.subtype === 'object' && schema.items) { - yield* getProperties(schema.items, dereferencedSchema, level + 1, { - ...meta, - path: [...path, 'items'], - }); - } else if (meta.subtype === 'array' && schema.items) { - yield* renderSchema(schema.items, dereferencedSchema, level + 1, { - path, - }); + } else if (schema.items) { + switch (baseNode.metadata && baseNode.metadata.subtype) { + case SchemaKind.Object: + yield* getProperties(schema.items, dereferencedSchema, level + 1, { + ...meta, + path: [...path, 'items'], + }); + break; + case SchemaKind.Array: + yield* renderSchema(schema.items, dereferencedSchema, level + 1, { + path, + }); + break; + } } } else if ('properties' in node) { // special case :P, it's diff --git a/src/utils/walk.ts b/src/utils/walk.ts index 2ab18682..4e1b6e27 100644 --- a/src/utils/walk.ts +++ b/src/utils/walk.ts @@ -20,7 +20,7 @@ const getCombiner = (node: JSONSchema4): JSONSchema4CombinerName | void => { }; function assignNodeSpecificFields(base: IBaseNode, node: JSONSchema4) { - switch (node.type) { + switch (getType(node)) { case SchemaKind.Array: (base as IArrayNode).items = node.array; (base as IArrayNode).additionalItems = node.additionalItems; @@ -33,20 +33,28 @@ function assignNodeSpecificFields(base: IBaseNode, node: JSONSchema4) { } } +function getType(node: JSONSchema4) { + if (Array.isArray(node.type)) { + return node.type.length === 1 ? node.type[0] : node.type; + } + + return node.type; +} + function processNode(node: JSONSchema4): SchemaNode | void { const combiner = getCombiner(node); if (node.type !== undefined && combiner === undefined) { const base: IBaseNode = { id: assignId(node), - type: node.type, + type: getType(node), validations: getValidations(node), annotations: getAnnotations(node), enum: node.enum, }; - if (Array.isArray(node.type)) { - if (node.type.includes('object')) { + if (Array.isArray(base.type)) { + if (base.type.includes('object')) { // special case :P assignNodeSpecificFields(base, { ...node,