Skip to content

Commit 8e72209

Browse files
author
Phil Sturgeon
authored
Merge pull request #3 from wework/examples
Support "advanced example" from JSON Schema
2 parents 7983655 + aa2e610 commit 8e72209

25 files changed

+560
-36
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Changelog
2+
All notable changes to this project will be documented in this file.
3+
4+
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5+
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6+
7+
## [Unreleased]
8+
9+
## [0.1.1] - 2018-04-09
10+
### Added
11+
* Convert `dependencies` to an allOf + oneOf OpenAPI-valid equivalent

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ A little NodeJS package to convert JSON Schema to [OpenAPI Schema Objects](https
77
* converts JSON Schema Draft 00 Wright (a.k.a draft v5) to OpenAPI 3.0 Schema Object
88
* switches `type: ['foo', 'null']` to `type: foo` and `nullable: true`
99
* supports deep structures with nested `allOf`s etc.
10-
* switches `patternProperties` to `x-patternProperties` in the Schema Object
10+
* switches `patternProperties` to `x-patternProperties`
11+
* converts `dependencies` to an allOf + oneOf OpenAPI-valid equivalent
1112

1213
## Installation
1314

index.js

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
const structs = ['allOf', 'anyOf', 'oneOf', 'not', 'items', 'additionalProperties'];
22

3+
function InvalidTypeError(message) {
4+
this.name = 'InvalidTypeError';
5+
this.message = message;
6+
}
7+
8+
InvalidTypeError.prototype = new Error();
9+
310
function convert(schema, options) {
411
options = options || {};
512
options.cloneSchema = ! (options.cloneSchema === false);
@@ -8,12 +15,18 @@ function convert(schema, options) {
815
schema = JSON.parse(JSON.stringify(schema));
916
}
1017

11-
delete schema['$schema'];
18+
schema = removeRootKeywords(schema);
1219
schema = convertSchema(schema);
1320

1421
return schema;
1522
}
1623

24+
function removeRootKeywords(schema) {
25+
delete schema['$schema'];
26+
delete schema['id'];
27+
return schema;
28+
}
29+
1730
function convertSchema(schema) {
1831
let i = 0;
1932
let j = 0;
@@ -47,7 +60,10 @@ function convertSchema(schema) {
4760

4861
}
4962

63+
validateType(schema.type);
64+
5065
schema = convertTypes(schema);
66+
schema = convertDependencies(schema);
5167

5268
if (typeof schema['patternProperties'] === 'object') {
5369
schema = convertPatternProperties(schema);
@@ -56,11 +72,19 @@ function convertSchema(schema) {
5672
return schema;
5773
}
5874

75+
function validateType(type) {
76+
const validTypes = ['null', 'boolean', 'object', 'array', 'number', 'string', 'integer'];
77+
const types = Array.isArray(type) ? type : [type];
78+
types.forEach(type => {
79+
if (validTypes.indexOf(type) < 0 && type !== undefined)
80+
throw new InvalidTypeError('Type "' + type + '" is not a valid type');
81+
});
82+
}
83+
5984
function convertProperties(properties) {
60-
var key
61-
, property
62-
, props = {}
63-
;
85+
let key = {};
86+
let property = {};
87+
let props = {};
6488

6589
for (key in properties) {
6690
property = properties[key];
@@ -70,6 +94,51 @@ function convertProperties(properties) {
7094
return props;
7195
}
7296

97+
function convertDependencies(schema) {
98+
const deps = schema.dependencies;
99+
if (typeof deps !== 'object') {
100+
return schema;
101+
}
102+
103+
// Turns the dependencies keyword into an allOf of oneOf's
104+
// "dependencies": {
105+
// "post-office-box": ["street-address"]
106+
// },
107+
//
108+
// becomes
109+
//
110+
// "allOf": [
111+
// {
112+
// "oneOf": [
113+
// {"not": {"required": ["post-office-box"]}},
114+
// {"required": ["post-office-box", "street-address"]}
115+
// ]
116+
// }
117+
//
118+
119+
delete schema['dependencies'];
120+
if (!Array.isArray(schema.allOf)) {
121+
schema.allOf = [];
122+
}
123+
124+
for (const key in deps) {
125+
const foo = {
126+
'oneOf': [
127+
{
128+
'not': {
129+
'required': [key]
130+
}
131+
},
132+
{
133+
'required': [].concat(key, deps[key])
134+
}
135+
]
136+
};
137+
schema.allOf.push(foo);
138+
}
139+
return schema;
140+
}
141+
73142
function convertTypes(schema) {
74143
var newType;
75144

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "json-schema-to-openapi-schema",
3-
"version": "0.1.0",
3+
"version": "0.1.1",
44
"description": "Converts a JSON Schema to OpenAPI Schema Object",
55
"main": "index.js",
66
"scripts": {
File renamed without changes.
File renamed without changes.

test/complex_schemas.js

Lines changed: 0 additions & 28 deletions
This file was deleted.

test/complex_schemas.test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
3+
const convert = require('../');
4+
const should = require('should');
5+
const getSchema = require('./helpers').getSchema;
6+
7+
['basic', 'address', 'calendar'].forEach(test => {
8+
it(`converts ${test}/openapi.json`, () => {
9+
const schema = getSchema(test + '/json-schema.json');
10+
const result = convert(schema);
11+
const expected = getSchema(test + '/openapi.json');
12+
13+
should(result).deepEqual(expected, 'converted');
14+
});
15+
16+
it(`converting ${test}/openapi.json in place`, () => {
17+
const schema = getSchema(test + '/json-schema.json');
18+
const result = convert(schema, { cloneSchema: false });
19+
const expected = getSchema(test + '/openapi.json');
20+
21+
should(schema).deepEqual(result, 'changed schema in place');
22+
should(result).deepEqual(expected, 'converted');
23+
});
24+
});

test/helpers.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const fs = require('fs');
2+
const join = require('path').join;
3+
4+
const getSchema = file => {
5+
const path = join(__dirname, 'schemas', file);
6+
return JSON.parse(fs.readFileSync(path));
7+
};
8+
9+
module.exports = { getSchema };

0 commit comments

Comments
 (0)