diff --git a/README.md b/README.md index 46f729e..337b293 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,8 @@ A little NodeJS package to convert JSON Schema to [OpenAPI Schema Objects](https * converts JSON Schema Draft 00 Wright (a.k.a draft v5) to OpenAPI 3.0 Schema Object * switches `type: ['foo', 'null']` to `type: foo` and `nullable: true` * supports deep structures with nested `allOf`s etc. -* switches `patternProperties` to `x-patternProperties` in the Schema Object +* switches `patternProperties` to `x-patternProperties` +* converts `dependencies` to an allOf + oneOf OpenAPI-valid equivalent ## Installation diff --git a/index.js b/index.js index 07bc3c3..57b20c5 100644 --- a/index.js +++ b/index.js @@ -61,7 +61,9 @@ function convertSchema(schema) { } validateType(schema.type); + schema = convertTypes(schema); + schema = convertDependencies(schema); if (typeof schema['patternProperties'] === 'object') { schema = convertPatternProperties(schema); @@ -80,10 +82,9 @@ function validateType(type) { } function convertProperties(properties) { - var key - , property - , props = {} - ; + let key = {}; + let property = {}; + let props = {}; for (key in properties) { property = properties[key]; @@ -93,6 +94,51 @@ function convertProperties(properties) { return props; } +function convertDependencies(schema) { + const deps = schema.dependencies; + if (typeof deps !== 'object') { + return schema; + } + + // Turns the dependencies keyword into an allOf of oneOf's + // "dependencies": { + // "post-office-box": ["street-address"] + // }, + // + // becomes + // + // "allOf": [ + // { + // "oneOf": [ + // {"not": {"required": ["post-office-box"]}}, + // {"required": ["post-office-box", "street-address"]} + // ] + // } + // + + delete schema['dependencies']; + if (!Array.isArray(schema.allOf)) { + schema.allOf = []; + } + + for (const key in deps) { + const foo = { + 'oneOf': [ + { + 'not': { + 'required': [key] + } + }, + { + 'required': [].concat(key, deps[key]) + } + ] + }; + schema.allOf.push(foo); + } + return schema; +} + function convertTypes(schema) { var newType; diff --git a/test/schemas/address/openapi.json b/test/schemas/address/openapi.json index 9fbf140..593c861 100644 --- a/test/schemas/address/openapi.json +++ b/test/schemas/address/openapi.json @@ -1,18 +1,28 @@ { - "description": "An Address following the convention of http://microformats.org/wiki/hcard", - "type": "object", - "properties": { - "post-office-box": { "type": "string" }, - "extended-address": { "type": "string" }, - "street-address": { "type": "string" }, - "locality":{ "type": "string" }, - "region": { "type": "string" }, - "postal-code": { "type": "string" }, - "country-name": { "type": "string"} + "description": "An Address following the convention of http://microformats.org/wiki/hcard", + "type": "object", + "properties": { + "post-office-box": { "type": "string" }, + "extended-address": { "type": "string" }, + "street-address": { "type": "string" }, + "locality":{ "type": "string" }, + "region": { "type": "string" }, + "postal-code": { "type": "string" }, + "country-name": { "type": "string"} + }, + "required": ["locality", "region", "country-name"], + "allOf": [ + { + "oneOf": [ + {"not": {"required": ["post-office-box"]}}, + {"required": ["post-office-box", "street-address"]} + ] }, - "required": ["locality", "region", "country-name"], - "x-json-schema-dependencies": { - "post-office-box": ["street-address"], - "extended-address": ["street-address"] + { + "oneOf": [ + {"not": {"required": ["extended-address"]}}, + {"required": ["extended-address", "street-address"]} + ] } + ] }