Big News: Socket Selected for OpenAI's Cybersecurity Grant Program.Details
Socket
Book a DemoSign in
Socket

json-schema-to-openapi-schema

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

json-schema-to-openapi-schema - npm Package Compare versions

Comparing version
0.1.0
to
0.1.1
+11
CHANGELOG.md
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.1.1] - 2018-04-09
### Added
* Convert `dependencies` to an allOf + oneOf OpenAPI-valid equivalent
'use strict';
const convert = require('../');
const should = require('should');
it('cloning schema by default', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: ['string', 'null'],
};
const result = convert(schema);
const expected = {
type: 'string',
nullable: true,
};
should(result).deepEqual(expected, 'result does not match the expected');
should(result).not.deepEqual(schema, 'the schema was modified in place');
});
it('cloning schema with cloneSchema option', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: ['string', 'null'],
};
const result = convert(schema, { cloneSchema: true });
const expected = {
type: 'string',
nullable: true,
};
should(result).deepEqual(expected, 'result does not match the expected');
should(result).not.deepEqual(schema, 'the schema was modified in place');
});
it('direct schema modification', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: ['string', 'null'],
};
const result = convert(schema, { cloneSchema: false });
const expected = {
type: 'string',
nullable: true,
};
should(result).deepEqual(expected, 'result does not match the expected');
should(result).deepEqual(schema, 'the schema was not modified in place');
});
'use strict';
const convert = require('../');
const should = require('should');
it('iterates allOfs and converts types', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
allOf: [
{
type: 'object',
required: ['foo'],
properties: {
foo: {
type: 'integer',
format: 'int64'
}
}
},
{
allOf: [
{
type: 'number',
format: 'double'
}
]
}
]
};
const result = convert(schema);
const expected = {
allOf: [
{
type: 'object',
required: ['foo'],
properties: {
foo: {
type: 'integer',
format: 'int64'
}
}
},
{
allOf: [
{
type: 'number',
format: 'double'
}
]
}
]
};
should(result).deepEqual(expected, 'iterated allOfs');
});
it('iterates anyOfs and converts types', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
anyOf: [
{
type: 'object',
required: ['foo'],
properties: {
foo: {
type: 'integer',
format: 'int64'
}
}
},
{
anyOf: [
{
type: 'object',
properties: {
bar: {
type: 'number',
format: 'double'
}
}
}
]
}
]
};
const result = convert(schema);
const expected = {
anyOf: [
{
type: 'object',
required: ['foo'],
properties: {
foo: {
type: 'integer',
format: 'int64'
}
}
},
{
anyOf: [
{
type: 'object',
properties: {
bar: {
type: 'number',
format: 'double'
}
}
}
]
}
]
};
should(result).deepEqual(expected, 'anyOfs iterated');
});
it('iterates oneOfs and converts types', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
oneOf: [
{
type: 'object',
required: ['foo'],
properties: {
foo: {
type: ['string', 'null']
}
}
},
{
oneOf: [
{
type: 'object',
properties: {
bar: {
type: ['string', 'null']
}
}
}
]
}
]
};
const result = convert(schema);
const expected = {
oneOf: [
{
type: 'object',
required: ['foo'],
properties: {
foo: {
type: 'string',
nullable: true
}
}
},
{
oneOf: [
{
type: 'object',
properties: {
bar: {
type: 'string',
nullable: true
}
}
}
]
}
]
};
should(result).deepEqual(expected, 'oneOfs iterated');
});
it('converts types in not', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'object',
properties: {
not: {
type: ['string', 'null'],
minLength: 8
}
}
};
const result = convert(schema);
const expected = {
type: 'object',
properties: {
not: {
type: 'string',
nullable: true,
minLength: 8
}
}
};
should(result).deepEqual(expected, 'not handled');
});
it('nested combination keywords', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
anyOf: [
{
allOf: [
{
type: 'object',
properties: {
foo: {
type: ['string', 'null']
}
}
},
{
type: 'object',
properties: {
bar: {
type: ['integer', 'null']
}
}
}
]
},
{
type: 'object',
properties: {
foo: {
type: 'string',
}
}
},
{
not: {
type: 'string',
example: 'foobar'
}
}
]
};
const result = convert(schema);
const expected = {
anyOf: [
{
allOf: [
{
type: 'object',
properties: {
foo: {
type: 'string',
nullable: true
}
}
},
{
type: 'object',
properties: {
bar: {
type: 'integer',
nullable: true
}
}
}
]
},
{
type: 'object',
properties: {
foo: {
type: 'string',
}
}
},
{
not: {
type: 'string',
example: 'foobar'
}
}
]
};
should(result).deepEqual(expected, 'nested combination keywords');
});
'use strict';
const convert = require('../');
const should = require('should');
const getSchema = require('./helpers').getSchema;
['basic', 'address', 'calendar'].forEach(test => {
it(`converts ${test}/openapi.json`, () => {
const schema = getSchema(test + '/json-schema.json');
const result = convert(schema);
const expected = getSchema(test + '/openapi.json');
should(result).deepEqual(expected, 'converted');
});
it(`converting ${test}/openapi.json in place`, () => {
const schema = getSchema(test + '/json-schema.json');
const result = convert(schema, { cloneSchema: false });
const expected = getSchema(test + '/openapi.json');
should(schema).deepEqual(result, 'changed schema in place');
should(result).deepEqual(expected, 'converted');
});
});
const fs = require('fs');
const join = require('path').join;
const getSchema = file => {
const path = join(__dirname, 'schemas', file);
return JSON.parse(fs.readFileSync(path));
};
module.exports = { getSchema };
'use strict';
const convert = require('../');
const should = require('should');
const getSchema = require('./helpers').getSchema;
it('dateTime is invalid type', () => {
const schema = { type: 'dateTime' };
should.throws(() => { convert(schema); }, /InvalidTypeError/);
});
it('foo is invalid type', () => {
const schema = { type: 'foo' };
should.throws(() => { convert(schema); }, /InvalidTypeError/);
});
it('invalid type inside complex schema', () => {
const schema = getSchema('invalid/json-schema.json');
should.throws(() => { convert(schema); }, /InvalidTypeError.*invalidtype/);
});
'use strict';
const convert = require('../');
const should = require('should');
it('items', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'array',
items: {
type: 'string',
format: 'date-time',
example: '2017-01-01T12:34:56Z'
}
};
const result = convert(schema);
const expected = {
type: 'array',
items: {
type: 'string',
format: 'date-time',
example: '2017-01-01T12:34:56Z'
}
};
should(result).deepEqual(expected, 'converted');
});
'use strict';
const convert = require('../');
const should = require('should');
it('adds `nullable: true` for `type: [string, null]`', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: ['string', 'null'],
};
const result = convert(schema);
should(result).deepEqual({
type: 'string',
nullable: true
});
});
it('does not add nullable for non null types', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'string'
};
const result = convert(schema);
should(result).deepEqual({
type: 'string'
});
});
'use strict';
const convert = require('../');
const should = require('should');
it('renames patternProperties to x-patternProperties', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'object',
additionalProperties: {
type: 'string'
},
patternProperties: {
'^[a-z]*$': {
type: 'string'
}
}
};
const result = convert(schema);
const expected = {
type: 'object',
additionalProperties: {
type: 'string'
},
'x-patternProperties': {
'^[a-z]*$': {
type: 'string'
}
}
};
should(result).deepEqual(expected);
});
'use strict';
const convert = require('../');
const should = require('should');
it('type array', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: ['string', 'null']
};
const result = convert(schema);
const expected = {
type: 'string',
nullable: true
};
should(result).deepEqual(expected);
});
it('properties', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'object',
required: ['bar'],
properties: {
foo: {
type: 'string',
},
bar: {
type: ['string', 'null']
}
}
};
const result = convert(schema);
const expected = {
type: 'object',
required: ['bar'],
properties: {
foo: {
type: 'string',
},
bar: {
type: 'string',
nullable: true
}
}
};
should(result).deepEqual(expected);
});
it('addionalProperties is false', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'object',
properties: {
foo: {
type: 'string',
}
},
additionalProperties: false
};
const result = convert(schema);
const expected = {
type: 'object',
properties: {
foo: {
type: 'string',
}
},
additionalProperties: false
};
should(result).deepEqual(expected, 'properties converted');
});
it('addionalProperties is true', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'object',
properties: {
foo: {
type: 'string',
}
},
additionalProperties: true
};
const result = convert(schema);
const expected = {
type: 'object',
properties: {
foo: {
type: 'string',
}
},
additionalProperties: true
};
should(result).deepEqual(expected);
});
it('addionalProperties is an object', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'object',
properties: {
foo: {
type: 'string',
}
},
additionalProperties: {
type: 'object',
properties: {
foo: {
type: 'string',
format: 'date-time'
}
}
}
};
const result = convert(schema);
const expected = {
type: 'object',
properties: {
foo: {
type: 'string'
}
},
additionalProperties: {
type: 'object',
properties: {
foo: {
type: 'string',
format: 'date-time'
}
}
}
};
should(result).deepEqual(expected, 'properties and additionalProperties converted');
});
'use strict';
const convert = require('../');
const should = require('should');
it('maintain readOnly and writeOnly props', () => {
const schema = {
type: 'object',
properties: {
prop1: {
type: 'string',
readOnly: true
},
prop2: {
type: 'string',
writeOnly: true
}
}
};
const result = convert(schema);
const expected = {
type: 'object',
properties: {
prop1: {
type: 'string',
readOnly: true
},
prop2: {
type: 'string',
writeOnly: true
}
}
};
should(result).deepEqual(expected);
});
it('deep schema', () => {
const schema = {
type: 'object',
required: ['prop1', 'prop2'],
properties: {
prop1: {
type: 'string',
readOnly: true
},
prop2: {
allOf: [
{
type: 'object',
required: ['prop3'],
properties: {
prop3: {
type: 'object',
readOnly: true
}
}
},
{
type: 'object',
properties: {
prop4: {
type: 'object',
readOnly: true
}
}
},
]
}
}
};
const result = convert(schema);
const expected = {
type: 'object',
required: ['prop1', 'prop2'],
properties: {
prop1: {
type: 'string',
readOnly: true
},
prop2: {
allOf: [
{
type: 'object',
required: ['prop3'],
properties: {
prop3: {
type: 'object',
readOnly: true
}
}
},
{
type: 'object',
properties: {
prop4: {
type: 'object',
readOnly: true
}
}
},
]
}
}
};
should(result).deepEqual(expected);
});
{
"$schema": "http://json-schema.org/draft-06/schema#",
"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"],
"dependencies": {
"post-office-box": ["street-address"],
"extended-address": ["street-address"]
}
}
{
"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"]}
]
},
{
"oneOf": [
{"not": {"required": ["extended-address"]}},
{"required": ["extended-address", "street-address"]}
]
}
]
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"allOf": [
{
"anyOf": [
{
"type": "object",
"properties": {
"cats": {
"type": "array",
"items": {
"type": "integer",
"format": "int64",
"example": [
1
]
}
}
}
},
{
"type": "object",
"properties": {
"dogs": {
"type": "array",
"items": {
"type": "integer",
"format": "int64",
"example": [
1
]
}
}
}
},
{
"type": "object",
"properties": {
"bring_cats": {
"type": "array",
"items": {
"allOf": [
{
"type": "object",
"properties": {
"email": {
"type": "string",
"example": "cats@email.com"
},
"sms": {
"type": [
"string",
"null"
],
"example": "+12345678"
},
"properties": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"example": {
"name": "Wookie"
}
}
}
},
{
"required": [
"email"
]
}
]
}
}
}
}
]
},
{
"type": "object",
"properties": {
"playground": {
"type": "object",
"required": [
"feeling",
"child"
],
"properties": {
"feeling": {
"type": "string",
"example": "Good feeling"
},
"child": {
"type": "object",
"required": [
"name",
"age"
],
"properties": {
"name": {
"type": "string",
"example": "Steven"
},
"age": {
"type": "integer",
"example": 5
}
}
},
"toy": {
"type": "object",
"properties": {
"breaks_easily": {
"type": "boolean",
"default": false
},
"color": {
"type": "string",
"description": "Color of the toy"
},
"type": {
"type": "string",
"enum": ["bucket", "shovel"],
"description": "Toy type"
}
}
}
}
}
}
}
]
}
{
"allOf": [
{
"anyOf": [
{
"type": "object",
"properties": {
"cats": {
"type": "array",
"items": {
"type": "integer",
"format": "int64",
"example": [
1
]
}
}
}
},
{
"type": "object",
"properties": {
"dogs": {
"type": "array",
"items": {
"type": "integer",
"format": "int64",
"example": [
1
]
}
}
}
},
{
"type": "object",
"properties": {
"bring_cats": {
"type": "array",
"items": {
"allOf": [
{
"type": "object",
"properties": {
"email": {
"type": "string",
"example": "cats@email.com"
},
"sms": {
"type": "string",
"nullable": true,
"example": "+12345678"
},
"properties": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"example": {
"name": "Wookie"
}
}
}
},
{
"required": [
"email"
]
}
]
}
}
}
}
]
},
{
"type": "object",
"properties": {
"playground": {
"type": "object",
"required": [
"feeling",
"child"
],
"properties": {
"feeling": {
"type": "string",
"example": "Good feeling"
},
"child": {
"type": "object",
"required": [
"name",
"age"
],
"properties": {
"name": {
"type": "string",
"example": "Steven"
},
"age": {
"type": "integer",
"example": 5
}
}
},
"toy": {
"type": "object",
"properties": {
"breaks_easily": {
"type": "boolean",
"default": false
},
"color": {
"type": "string",
"description": "Color of the toy"
},
"type": {
"type": "string",
"enum": ["bucket", "shovel"],
"description": "Toy type"
}
}
}
}
}
}
}
]
}
{
"$schema": "http://json-schema.org/draft-06/schema#",
"description": "A representation of an event",
"type": "object",
"required": [ "dtstart", "summary" ],
"properties": {
"dtstart": {
"format": "date-time",
"type": "string",
"description": "Event starting time"
},
"dtend": {
"format": "date-time",
"type": "string",
"description": "Event ending time"
},
"summary": { "type": "string" },
"location": { "type": "string" },
"url": { "type": "string", "format": "uri" },
"duration": {
"format": "time",
"type": "string",
"description": "Event duration"
},
"rdate": {
"format": "date-time",
"type": "string",
"description": "Recurrence date"
},
"rrule": {
"type": "string",
"description": "Recurrence rule"
},
"category": { "type": "string" },
"description": { "type": "string" },
"geo": { "$ref": "http://json-schema.org/geo" }
}
}
{
"description": "A representation of an event",
"type": "object",
"required": [ "dtstart", "summary" ],
"properties": {
"dtstart": {
"format": "date-time",
"type": "string",
"description": "Event starting time"
},
"dtend": {
"format": "date-time",
"type": "string",
"description": "Event ending time"
},
"summary": { "type": "string" },
"location": { "type": "string" },
"url": { "type": "string", "format": "uri" },
"duration": {
"format": "time",
"type": "string",
"description": "Event duration"
},
"rdate": {
"format": "date-time",
"type": "string",
"description": "Recurrence date"
},
"rrule": {
"type": "string",
"description": "Recurrence rule"
},
"category": { "type": "string" },
"description": { "type": "string" },
"geo": { "$ref": "http://json-schema.org/geo" }
}
}
{
"id": "http://some.site.somewhere/entry-schema#",
"$schema": "http://json-schema.org/draft-06/schema#",
"description": "schema for an fstab entry",
"type": "object",
"required": [ "storage" ],
"properties": {
"storage": {
"type": "object",
"oneOf": [
{ "$ref": "#/definitions/diskDevice" },
{ "$ref": "#/definitions/diskUUID" },
{ "$ref": "#/definitions/nfs" },
{ "$ref": "#/definitions/tmpfs" }
]
},
"fstype": {
"enum": [ "ext3", "ext4", "btrfs" ]
},
"options": {
"type": "array",
"minItems": 1,
"items": { "type": "string" },
"uniqueItems": true
},
"readonly": { "type": "boolean" }
},
"definitions": {
"diskDevice": {
"properties": {
"type": { "enum": [ "disk" ] },
"device": {
"type": "string",
"pattern": "^/dev/[^/]+(/[^/]+)*$"
}
},
"required": [ "type", "device" ],
"additionalProperties": false
},
"diskUUID": {
"properties": {
"type": { "enum": [ "disk" ] },
"label": {
"type": "string",
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
}
},
"required": [ "type", "label" ],
"additionalProperties": false
},
"nfs": {
"properties": {
"type": { "enum": [ "nfs" ] },
"remotePath": {
"type": "string",
"pattern": "^(/[^/]+)+$"
},
"server": {
"type": "string",
"oneOf": [
{ "format": "hostname" },
{ "format": "ipv4" },
{ "format": "ipv6" }
]
}
},
"required": [ "type", "server", "remotePath" ],
"additionalProperties": false
},
"tmpfs": {
"properties": {
"type": { "enum": [ "tmpfs" ] },
"sizeInMB": {
"type": "integer",
"minimum": 16,
"maximum": 512
}
},
"required": [ "type", "sizeInMB" ],
"additionalProperties": false
}
}
}
{
"description": "schema for an fstab entry",
"type": "object",
"required": [ "storage" ],
"properties": {
"storage": {
"type": "object",
"oneOf": [
{ "$ref": "#/definitions/diskDevice" },
{ "$ref": "#/definitions/diskUUID" },
{ "$ref": "#/definitions/nfs" },
{ "$ref": "#/definitions/tmpfs" }
]
},
"fstype": {
"enum": [ "ext3", "ext4", "btrfs" ]
},
"options": {
"type": "array",
"minItems": 1,
"items": { "type": "string" },
"uniqueItems": true
},
"readonly": { "type": "boolean" }
},
"definitions": {
"diskDevice": {
"properties": {
"type": { "enum": [ "disk" ] },
"device": {
"type": "string",
"pattern": "^/dev/[^/]+(/[^/]+)*$"
}
},
"required": [ "type", "device" ],
"additionalProperties": false
},
"diskUUID": {
"properties": {
"type": { "enum": [ "disk" ] },
"label": {
"type": "string",
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
}
},
"required": [ "type", "label" ],
"additionalProperties": false
},
"nfs": {
"properties": {
"type": { "enum": [ "nfs" ] },
"remotePath": {
"type": "string",
"pattern": "^(/[^/]+)+$"
},
"server": {
"type": "string",
"oneOf": [
{ "format": "hostname" },
{ "format": "ipv4" },
{ "format": "ipv6" }
]
}
},
"required": [ "type", "server", "remotePath" ],
"additionalProperties": false
},
"tmpfs": {
"properties": {
"type": { "enum": [ "tmpfs" ] },
"sizeInMB": {
"type": "integer",
"minimum": 16,
"maximum": 512
}
},
"required": [ "type", "sizeInMB" ],
"additionalProperties": false
}
}
}
{
"allOf": [
{
"anyOf": [
{
"type": "object",
"properties": {
"cats": {
"type": "array",
"items": {
"type": "integer",
"format": "int64",
"example": [
1
]
}
}
}
},
{
"type": "object",
"properties": {
"dogs": {
"type": "array",
"items": {
"type": "integer",
"format": "int64",
"example": [
1
]
}
}
}
},
{
"type": "object",
"properties": {
"bring_cats": {
"type": "array",
"items": {
"allOf": [
{
"type": "object",
"properties": {
"email": {
"type": "string",
"example": "cats@email.com"
},
"sms": {
"type": "string",
"nullable": true,
"example": "+12345678"
},
"properties": {
"type": "object",
"additionalProperties": {
"type": "invalidtype"
},
"example": {
"name": "Wookie"
}
}
}
},
{
"required": [
"email"
]
}
]
}
}
}
}
]
},
{
"type": "object",
"properties": {
"playground": {
"type": "object",
"required": [
"feeling",
"child"
],
"properties": {
"feeling": {
"type": "string",
"example": "Good feeling"
},
"child": {
"type": "object",
"required": [
"name",
"age"
],
"properties": {
"name": {
"type": "string",
"example": "Steven"
},
"age": {
"type": "integer",
"example": 5
}
}
},
"toy": {
"type": "object",
"properties": {
"breaks_easily": {
"type": "boolean",
"default": false
},
"color": {
"type": "string",
"description": "Color of the toy"
},
"type": {
"type": "string",
"enum": ["bucket", "shovel"],
"description": "Toy type"
}
}
}
}
}
}
}
]
}
+74
-5
const structs = ['allOf', 'anyOf', 'oneOf', 'not', 'items', 'additionalProperties'];
function InvalidTypeError(message) {
this.name = 'InvalidTypeError';
this.message = message;
}
InvalidTypeError.prototype = new Error();
function convert(schema, options) {

@@ -11,3 +18,3 @@ options = options || {};

delete schema['$schema'];
schema = removeRootKeywords(schema);
schema = convertSchema(schema);

@@ -18,2 +25,8 @@

function removeRootKeywords(schema) {
delete schema['$schema'];
delete schema['id'];
return schema;
}
function convertSchema(schema) {

@@ -52,3 +65,6 @@ let i = 0;

validateType(schema.type);
schema = convertTypes(schema);
schema = convertDependencies(schema);

@@ -62,7 +78,15 @@ if (typeof schema['patternProperties'] === 'object') {

function validateType(type) {
const validTypes = ['null', 'boolean', 'object', 'array', 'number', 'string', 'integer'];
const types = Array.isArray(type) ? type : [type];
types.forEach(type => {
if (validTypes.indexOf(type) < 0 && type !== undefined)
throw new InvalidTypeError('Type "' + type + '" is not a valid type');
});
}
function convertProperties(properties) {
var key
, property
, props = {}
;
let key = {};
let property = {};
let props = {};

@@ -77,2 +101,47 @@ for (key in properties) {

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) {

@@ -79,0 +148,0 @@ var newType;

+1
-1
{
"name": "json-schema-to-openapi-schema",
"version": "0.1.0",
"version": "0.1.1",
"description": "Converts a JSON Schema to OpenAPI Schema Object",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -1,2 +0,2 @@

# OpenAPI Schema to JSON Schema
# JSON Schema to OpenAPI Schema

@@ -10,3 +10,4 @@ A little NodeJS package to convert JSON Schema to [OpenAPI Schema Objects](https://swagger.io/specification/#schemaObject).

* 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

@@ -13,0 +14,0 @@ ## Installation

'use strict';
const convert = require('../');
const should = require('should');
it('cloning schema by default', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: ['string', 'null'],
};
const result = convert(schema);
const expected = {
type: 'string',
nullable: true,
};
should(result).deepEqual(expected, 'result does not match the expected');
should(result).not.deepEqual(schema, 'the schema was modified in place');
});
it('cloning schema with cloneSchema option', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: ['string', 'null'],
};
const result = convert(schema, { cloneSchema: true });
const expected = {
type: 'string',
nullable: true,
};
should(result).deepEqual(expected, 'result does not match the expected');
should(result).not.deepEqual(schema, 'the schema was modified in place');
});
it('direct schema modification', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: ['string', 'null'],
};
const result = convert(schema, { cloneSchema: false });
const expected = {
type: 'string',
nullable: true,
};
should(result).deepEqual(expected, 'result does not match the expected');
should(result).deepEqual(schema, 'the schema was not modified in place');
});
'use strict';
const convert = require('../');
const should = require('should');
it('iterates allOfs and converts types', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
allOf: [
{
type: 'object',
required: ['foo'],
properties: {
foo: {
type: 'integer',
format: 'int64'
}
}
},
{
allOf: [
{
type: 'number',
format: 'double'
}
]
}
]
};
const result = convert(schema);
const expected = {
allOf: [
{
type: 'object',
required: ['foo'],
properties: {
foo: {
type: 'integer',
format: 'int64'
}
}
},
{
allOf: [
{
type: 'number',
format: 'double'
}
]
}
]
};
should(result).deepEqual(expected, 'iterated allOfs');
});
it('iterates anyOfs and converts types', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
anyOf: [
{
type: 'object',
required: ['foo'],
properties: {
foo: {
type: 'integer',
format: 'int64'
}
}
},
{
anyOf: [
{
type: 'object',
properties: {
bar: {
type: 'number',
format: 'double'
}
}
}
]
}
]
};
const result = convert(schema);
const expected = {
anyOf: [
{
type: 'object',
required: ['foo'],
properties: {
foo: {
type: 'integer',
format: 'int64'
}
}
},
{
anyOf: [
{
type: 'object',
properties: {
bar: {
type: 'number',
format: 'double'
}
}
}
]
}
]
};
should(result).deepEqual(expected, 'anyOfs iterated');
});
it('iterates oneOfs and converts types', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
oneOf: [
{
type: 'object',
required: ['foo'],
properties: {
foo: {
type: ['string', 'null']
}
}
},
{
oneOf: [
{
type: 'object',
properties: {
bar: {
type: ['string', 'null']
}
}
}
]
}
]
};
const result = convert(schema);
const expected = {
oneOf: [
{
type: 'object',
required: ['foo'],
properties: {
foo: {
type: 'string',
nullable: true
}
}
},
{
oneOf: [
{
type: 'object',
properties: {
bar: {
type: 'string',
nullable: true
}
}
}
]
}
]
};
should(result).deepEqual(expected, 'oneOfs iterated');
});
it('converts types in not', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'object',
properties: {
not: {
type: ['string', 'null'],
minLength: 8
}
}
};
const result = convert(schema);
const expected = {
type: 'object',
properties: {
not: {
type: 'string',
nullable: true,
minLength: 8
}
}
};
should(result).deepEqual(expected, 'not handled');
});
it('nested combination keywords', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
anyOf: [
{
allOf: [
{
type: 'object',
properties: {
foo: {
type: ['string', 'null']
}
}
},
{
type: 'object',
properties: {
bar: {
type: ['integer', 'null']
}
}
}
]
},
{
type: 'object',
properties: {
foo: {
type: 'string',
}
}
},
{
not: {
type: 'string',
example: 'foobar'
}
}
]
};
const result = convert(schema);
const expected = {
anyOf: [
{
allOf: [
{
type: 'object',
properties: {
foo: {
type: 'string',
nullable: true
}
}
},
{
type: 'object',
properties: {
bar: {
type: 'integer',
nullable: true
}
}
}
]
},
{
type: 'object',
properties: {
foo: {
type: 'string',
}
}
},
{
not: {
type: 'string',
example: 'foobar'
}
}
]
};
should(result).deepEqual(expected, 'nested combination keywords');
});
'use strict';
const convert = require('../');
const should = require('should');
const fs = require('fs');
const join = require('path').join;
it('complex schema', () => {
const schema = getSchema('json-schema-expected.json');
const result = convert(schema);
const expected = getSchema('openapi-schema.json');
should(result).deepEqual(expected, 'converted');
});
it('converting complex schema in place', () => {
const schema = getSchema('json-schema-expected.json');
const result = convert(schema, { cloneSchema: false });
const expected = getSchema('openapi-schema.json');
should(schema).deepEqual(result, 'changed schema in place');
should(result).deepEqual(expected, 'converted');
});
function getSchema(file) {
const path = join(__dirname, 'schemas', file);
return JSON.parse(fs.readFileSync(path));
}
'use strict';
const convert = require('../');
const should = require('should');
it('items', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'array',
items: {
type: 'string',
format: 'date-time',
example: '2017-01-01T12:34:56Z'
}
};
const result = convert(schema);
const expected = {
type: 'array',
items: {
type: 'string',
format: 'date-time',
example: '2017-01-01T12:34:56Z'
}
};
should(result).deepEqual(expected, 'converted');
});
'use strict';
const convert = require('../');
const should = require('should');
it('adds `nullable: true` for `type: [string, null]`', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: ['string', 'null'],
};
const result = convert(schema);
should(result).deepEqual({
type: 'string',
nullable: true
});
});
it('does not add nullable for non null types', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'string'
};
const result = convert(schema);
should(result).deepEqual({
type: 'string'
});
});
'use strict';
const convert = require('../');
const should = require('should');
it('renames patternProperties to x-patternProperties', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'object',
additionalProperties: {
type: 'string'
},
patternProperties: {
'^[a-z]*$': {
type: 'string'
}
}
};
const result = convert(schema);
const expected = {
type: 'object',
additionalProperties: {
type: 'string'
},
'x-patternProperties': {
'^[a-z]*$': {
type: 'string'
}
}
};
should(result).deepEqual(expected);
});
'use strict';
const convert = require('../');
const should = require('should');
it('type array', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: ['string', 'null']
};
const result = convert(schema);
const expected = {
type: 'string',
nullable: true
};
should(result).deepEqual(expected);
});
it('properties', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'object',
required: ['bar'],
properties: {
foo: {
type: 'string',
},
bar: {
type: ['string', 'null']
}
}
};
const result = convert(schema);
const expected = {
type: 'object',
required: ['bar'],
properties: {
foo: {
type: 'string',
},
bar: {
type: 'string',
nullable: true
}
}
};
should(result).deepEqual(expected);
});
it('addionalProperties is false', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'object',
properties: {
foo: {
type: 'string',
}
},
additionalProperties: false
};
const result = convert(schema);
const expected = {
type: 'object',
properties: {
foo: {
type: 'string',
}
},
additionalProperties: false
};
should(result).deepEqual(expected, 'properties converted');
});
it('addionalProperties is true', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'object',
properties: {
foo: {
type: 'string',
}
},
additionalProperties: true
};
const result = convert(schema);
const expected = {
type: 'object',
properties: {
foo: {
type: 'string',
}
},
additionalProperties: true
};
should(result).deepEqual(expected);
});
it('addionalProperties is an object', () => {
const schema = {
$schema: 'http://json-schema.org/draft-04/schema#',
type: 'object',
properties: {
foo: {
type: 'string',
}
},
additionalProperties: {
type: 'object',
properties: {
foo: {
type: 'string',
format: 'date-time'
}
}
}
};
const result = convert(schema);
const expected = {
type: 'object',
properties: {
foo: {
type: 'string'
}
},
additionalProperties: {
type: 'object',
properties: {
foo: {
type: 'string',
format: 'date-time'
}
}
}
};
should(result).deepEqual(expected, 'properties and additionalProperties converted');
});
'use strict';
const convert = require('../');
const should = require('should');
it('maintain readOnly and writeOnly props', () => {
const schema = {
type: 'object',
properties: {
prop1: {
type: 'string',
readOnly: true
},
prop2: {
type: 'string',
writeOnly: true
}
}
};
const result = convert(schema);
const expected = {
type: 'object',
properties: {
prop1: {
type: 'string',
readOnly: true
},
prop2: {
type: 'string',
writeOnly: true
}
}
};
should(result).deepEqual(expected);
});
it('deep schema', () => {
const schema = {
type: 'object',
required: ['prop1', 'prop2'],
properties: {
prop1: {
type: 'string',
readOnly: true
},
prop2: {
allOf: [
{
type: 'object',
required: ['prop3'],
properties: {
prop3: {
type: 'object',
readOnly: true
}
}
},
{
type: 'object',
properties: {
prop4: {
type: 'object',
readOnly: true
}
}
},
]
}
}
};
const result = convert(schema);
const expected = {
type: 'object',
required: ['prop1', 'prop2'],
properties: {
prop1: {
type: 'string',
readOnly: true
},
prop2: {
allOf: [
{
type: 'object',
required: ['prop3'],
properties: {
prop3: {
type: 'object',
readOnly: true
}
}
},
{
type: 'object',
properties: {
prop4: {
type: 'object',
readOnly: true
}
}
},
]
}
}
};
should(result).deepEqual(expected);
});
{
"$schema": "http://json-schema.org/draft-04/schema#",
"allOf": [
{
"anyOf": [
{
"type": "object",
"properties": {
"cats": {
"type": "array",
"items": {
"type": "integer",
"format": "int64",
"example": [
1
]
}
}
}
},
{
"type": "object",
"properties": {
"dogs": {
"type": "array",
"items": {
"type": "integer",
"format": "int64",
"example": [
1
]
}
}
}
},
{
"type": "object",
"properties": {
"bring_cats": {
"type": "array",
"items": {
"allOf": [
{
"type": "object",
"properties": {
"email": {
"type": "string",
"example": "cats@email.com"
},
"sms": {
"type": [
"string",
"null"
],
"example": "+12345678"
},
"properties": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"example": {
"name": "Wookie"
}
}
}
},
{
"required": [
"email"
]
}
]
}
}
}
}
]
},
{
"type": "object",
"properties": {
"playground": {
"type": "object",
"required": [
"feeling",
"child"
],
"properties": {
"feeling": {
"type": "string",
"example": "Good feeling"
},
"child": {
"type": "object",
"required": [
"name",
"age"
],
"properties": {
"name": {
"type": "string",
"example": "Steven"
},
"age": {
"type": "integer",
"example": 5
}
}
},
"toy": {
"type": "object",
"properties": {
"breaks_easily": {
"type": "boolean",
"default": false
},
"color": {
"type": "string",
"description": "Color of the toy"
},
"type": {
"type": "string",
"enum": ["bucket", "shovel"],
"description": "Toy type"
}
}
}
}
}
}
}
]
}
{
"allOf": [
{
"anyOf": [
{
"type": "object",
"properties": {
"cats": {
"type": "array",
"items": {
"type": "integer",
"format": "int64",
"example": [
1
]
}
}
}
},
{
"type": "object",
"properties": {
"dogs": {
"type": "array",
"items": {
"type": "integer",
"format": "int64",
"example": [
1
]
}
}
}
},
{
"type": "object",
"properties": {
"bring_cats": {
"type": "array",
"items": {
"allOf": [
{
"type": "object",
"properties": {
"email": {
"type": "string",
"example": "cats@email.com"
},
"sms": {
"type": "string",
"nullable": true,
"example": "+12345678"
},
"properties": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"example": {
"name": "Wookie"
}
}
}
},
{
"required": [
"email"
]
}
]
}
}
}
}
]
},
{
"type": "object",
"properties": {
"playground": {
"type": "object",
"required": [
"feeling",
"child"
],
"properties": {
"feeling": {
"type": "string",
"example": "Good feeling"
},
"child": {
"type": "object",
"required": [
"name",
"age"
],
"properties": {
"name": {
"type": "string",
"example": "Steven"
},
"age": {
"type": "integer",
"example": 5
}
}
},
"toy": {
"type": "object",
"properties": {
"breaks_easily": {
"type": "boolean",
"default": false
},
"color": {
"type": "string",
"description": "Color of the toy"
},
"type": {
"type": "string",
"enum": ["bucket", "shovel"],
"description": "Toy type"
}
}
}
}
}
}
}
]
}