From 074872b7eec06b7cdb1632b2ed0e5e16931f6329 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Fri, 10 Mar 2017 13:29:26 +0100 Subject: [PATCH] Allow oneOf / anyOf to be used & displayed for root schema definitions --- lib/components/JsonSchema/json-schema.html | 11 ++++- lib/components/JsonSchema/json-schema.scss | 4 ++ lib/components/JsonSchema/json-schema.ts | 51 +++++++++++++++------- lib/services/schema-helper.service.ts | 26 ++++++++--- lib/services/schema-normalizer.service.ts | 12 +++++ 5 files changed, 81 insertions(+), 23 deletions(-) diff --git a/lib/components/JsonSchema/json-schema.html b/lib/components/JsonSchema/json-schema.html index 8ab87420..f1238537 100644 --- a/lib/components/JsonSchema/json-schema.html +++ b/lib/components/JsonSchema/json-schema.html @@ -46,9 +46,17 @@ [nestOdd]="!nestOdd" [isRequestSchema]="isRequestSchema"> +
+ {{schema._choiceTitle}} + + + +
+ - + !prop.readOnly); - } + if (this.schema._wrapped) { + this.schema._wrapped.forEach((schema) => { + SchemaHelper.preprocessProperties(schema, this.normPointer, { + childFor: this.childFor, + discriminator: this.discriminator + }); - if (this.optionsService.options.requiredPropsFirst) { - SchemaHelper.moveRequiredPropsFirst(this.properties, this.schema.required); - } + let properties = schema._properties || []; - this._hasSubSchemas = this.properties && this.properties.some( - propSchema => { - if (propSchema.type === 'array') { - propSchema = propSchema.items; + if (this.isRequestSchema) { + properties = properties.filter(prop => !prop.readOnly); } - return (propSchema && propSchema.type === 'object' && propSchema._pointer); - }); - if (this.properties.length === 1) { - this.properties[0].expanded = true; + if (this.optionsService.options.requiredPropsFirst) { + SchemaHelper.moveRequiredPropsFirst(properties, schema.required); + } + + this._hasSubSchemas = properties && properties.some( + propSchema => { + if (propSchema.type === 'array') { + propSchema = propSchema.items; + } + return (propSchema && propSchema.type === 'object' && propSchema._pointer); + }); + + if (properties.length === 1) { + properties[0].expanded = true; + } + + schema.displayProperties = properties + }) } } diff --git a/lib/services/schema-helper.service.ts b/lib/services/schema-helper.service.ts index 9f07b546..82912337 100644 --- a/lib/services/schema-helper.service.ts +++ b/lib/services/schema-helper.service.ts @@ -85,17 +85,33 @@ const injectors = { }, object: { check: (propertySchema) => { - return propertySchema.type === 'object' && (propertySchema.properties || + let isObject = propertySchema.type === 'object' && (propertySchema.properties || typeof propertySchema.additionalProperties === 'object'); + + let isChoiceObject = propertySchema.oneOf && propertySchema.oneOf.length > 0 || + propertySchema.anyOf && propertySchema.anyOf.length > 0 + + return isObject || isChoiceObject; }, inject: (injectTo, propertySchema = injectTo) => { - let baseName = propertySchema._pointer && JsonPointer.baseName(propertySchema._pointer); - injectTo._displayType = propertySchema.title || baseName || 'object'; injectTo._widgetType = 'object'; + if (propertySchema.type === 'object') { + let baseName = propertySchema._pointer && JsonPointer.baseName(propertySchema._pointer); + injectTo._displayType = propertySchema.title || baseName || 'object'; + injectTo._wrapped = [propertySchema]; + } else if (propertySchema.oneOf) { + injectTo._displayType = 'oneOf'; + injectTo._choiceTitle = 'One of'; + injectTo._wrapped = propertySchema.oneOf + } else if (propertySchema.anyOf) { + injectTo._displayType = 'anyOf'; + injectTo._choiceTitle = 'Any of'; + injectTo._wrapped = propertySchema.anyOf + } } }, noType: { - check: (propertySchema) => !propertySchema.type, + check: (propertySchema) => !propertySchema.type && !propertySchema.oneOf && !propertySchema.anyOf, inject: (injectTo) => { injectTo._displayType = '< anything >'; injectTo._displayTypeHint = 'This field may contain data of any type'; @@ -110,7 +126,7 @@ const injectors = { return (!propertySchema.properties || !Object.keys(propertySchema.properties).length) && (typeof propertySchema.additionalProperties !== 'object'); } - return (propertySchema.type !== 'array') && propertySchema.type; + return (propertySchema.type !== 'array' && !propertySchema.oneOf && !propertySchema.anyOf) && propertySchema.type; }, inject: (injectTo, propertySchema = injectTo) => { injectTo.isTrivial = true; diff --git a/lib/services/schema-normalizer.service.ts b/lib/services/schema-normalizer.service.ts index d3940bb2..3583b168 100644 --- a/lib/services/schema-normalizer.service.ts +++ b/lib/services/schema-normalizer.service.ts @@ -13,6 +13,8 @@ interface Reference { interface Schema { properties: any; allOf: any; + oneOf: any; + anyOf: any; items: any; additionalProperties: any; } @@ -73,6 +75,16 @@ class SchemaWalker { SchemaWalker.walkEach(obj.allOf, ptr, visitor); } + if (obj.oneOf) { + let ptr = JsonPointer.join(pointer, ['oneOf']); + SchemaWalker.walkEach(obj.oneOf, ptr, visitor); + } + + if (obj.anyOf) { + let ptr = JsonPointer.join(pointer, ['anyOf']); + SchemaWalker.walkEach(obj.anyOf, ptr, visitor); + } + if (obj.items) { let ptr = JsonPointer.join(pointer, ['items']); if (Array.isArray(obj.items)) {