diff --git a/README.md b/README.md index 51bfda7..15ef5ae 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,11 @@ ![Node.js CI](https://github.com/JaredCE/json-schema-to-openAPI-schema-object/actions/workflows/node.js.yml/badge.svg) ![version](https://img.shields.io/npm/v/json-schema-for-openapi.svg?style=flat-square) - # json-schema-for-openapi Converts a standard [JSON Schema](https://json-schema.org/understanding-json-schema/index.html) to a compatible [OpenAPI v3.0.X Schema Object](https://spec.openapis.org/oas/v3.0.3#schema-object). -As of version 0.3.0, it is now advised to run a schema through a de-referencer like: https://apitools.dev/json-schema-ref-parser/ to properly deal with `$ref`. I have removed my own poor implementation of de-referencing JSON schemas since there are libraries that can do it better than I can. +As of version 0.3.0, it is now advised to run a schema through a de-referencer like: to properly deal with `$ref`. I have removed my own poor implementation of de-referencing JSON schemas since there are libraries that can do it better than I can. It should be noted, that de-referencing libraries have their own issues and might not be able to properly parse your JSON/output a schema you might expect. Due to the way OpenAPI v3.0.X Schema Object's are handled, should the referencing not be 100% correct you might face issues using this library and its output to be used with OpenAPI 3.0.X. @@ -17,6 +16,7 @@ This attempts to massage the standard JSON Schema to a compatible OpenAPI v3.0.X ### Items as an Array to Object This will convert a schema of: + ```json { "type": "object", @@ -191,7 +191,11 @@ This will try to convert `"dependencies":`, `"dependentRequired":` and `"depende It will try to convert an If/Then/Else schema statement to a valid `"OneOf"` schema. -## Installation and Usage: +### PatternProperties + +It will convert `"patternProperties"` into `"x-patternProperties"`. + +## Installation and Usage Install via npm: `npm install json-schema-for-openapi`. diff --git a/src/Convertor.js b/src/Convertor.js index 7ac3847..308b038 100644 --- a/src/Convertor.js +++ b/src/Convertor.js @@ -47,6 +47,7 @@ class Convertor { 'description', 'format', 'default', + 'x-patternProperties' ] let validSchemaFields = [ @@ -120,6 +121,7 @@ class Convertor { this.convertNullProperty(schema) this.convertDefaultValues(schema) this.convertOneOfAnyOfNulls(schema) + this.convertPatternProperties(schema) this.removeInvalidFields(schema) } @@ -444,6 +446,14 @@ class Convertor { } } } + + convertPatternProperties(schema) { + if (schema?.patternProperties) { + schema['x-patternProperties'] = schema['patternProperties']; + delete schema['patternProperties']; + schema.additionalProperties ??= true; + } + } } module.exports = Convertor diff --git a/test/schemas/patternProperties/patternProperties.json b/test/schemas/patternProperties/patternProperties.json new file mode 100644 index 0000000..a051050 --- /dev/null +++ b/test/schemas/patternProperties/patternProperties.json @@ -0,0 +1,14 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "JSON API Schema", + "description": "This is a schema for responses in the JSON API format. For more, see http://jsonapi.org", + "type": "object", + "patternProperties": { + "^([0-1]?[0-9]|2[0-3]):[0-5][0-9](?::[0-5][0-9])?$": { + "timeData": { + "type": "string" + } + } + } +} + diff --git a/test/src/Convertor.spec.js b/test/src/Convertor.spec.js index e9905d6..118cd8b 100644 --- a/test/src/Convertor.spec.js +++ b/test/src/Convertor.spec.js @@ -53,6 +53,8 @@ const listOfBannedSchemas = require('../schemas/SchemasThatCannotBeConverted/lis // anyOf/oneOf Nulls const oneOfNull = require('../schemas/ofNulls/oneOfNull.json') const anyOfNull = require('../schemas/ofNulls/anyOfNull.json') +// patternProperties +const patternProperties = require('../schemas/patternProperties/patternProperties.json') // OpenAPI const basicOpenAPI = require('../openAPI/basic.json') @@ -91,14 +93,14 @@ describe('Convertor', () => { expect(Convertor).to.not.have.a.property('specialSchemaFields') expect(convertor).to.have.a.property('specialSchemaFields') expect(convertor.specialSchemaFields).to.be.an('Array') - expect(convertor.specialSchemaFields.length).to.be.equal(11) + expect(convertor.specialSchemaFields.length).to.be.equal(12) }); it('should have a property of this.validSchemaFields', function() { expect(Convertor).to.not.have.a.property('validSchemaFields') expect(convertor).to.have.a.property('validSchemaFields') expect(convertor.validSchemaFields).to.be.an('Array') - expect(convertor.validSchemaFields.length).to.be.equal(36) + expect(convertor.validSchemaFields.length).to.be.equal(37) }); it('should have a property of this.components', function() { @@ -633,6 +635,24 @@ describe('Convertor', () => { }); }); + describe('patternProperties', () => { + it('should convert patternProperties into an x-patternProperties', async function () { + const newConvertor = new Convertor(patternProperties) + const result = newConvertor.convert('basic') + expect(result.schemas.basic).to.have.property('x-patternProperties') + expect(result.schemas.basic['x-patternProperties']).to.have.property('^([0-1]?[0-9]|2[0-3]):[0-5][0-9](?::[0-5][0-9])?$') + + const cloned = JSON.parse(JSON.stringify(basicOpenAPI)) + Object.assign(cloned, {components: result}) + expect(cloned).to.have.property('components') + expect(cloned.components).to.have.property('schemas') + expect(cloned.components.schemas).to.have.property('basic') + let valid = await validator.validateInner(cloned, {}) + expect(valid).to.be.true + }) + + }) + xdescribe('use a repo with lots of schemas to find failing ones', () => { it('should convert all schemas successfully', async function() { this.timeout(1000000);