Skip to content

Commit aa27888

Browse files
author
Mika Kunnas
committed
initial commit
0 parents  commit aa27888

17 files changed

+2380
-0
lines changed

.eslintrc.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"env": {
3+
"node": true
4+
},
5+
"extends": "eslint:recommended",
6+
"rules": {
7+
"indent": [
8+
"error",
9+
"tab",
10+
{"SwitchCase": 1}
11+
],
12+
"linebreak-style": [
13+
"error",
14+
"unix"
15+
],
16+
"quotes": [
17+
"error",
18+
"single"
19+
],
20+
"semi": [
21+
"error",
22+
"always"
23+
]
24+
}
25+
}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.swp
2+
node_modules

README.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# OpenAPI Schema to JSON Schema
2+
3+
A little NodeJS package to convert OpenAPI Schema Object to JSON Schema. Currently converts from [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md) to [JSON Schema Draft 4](http://json-schema.org/specification-links.html#draft-4).
4+
5+
## Why?
6+
7+
OpenAPI is a specification for describing RESTful APIs. OpenAPI 3.0 allows us to describe the structures of request and response payloads in a detailed manner. This would, theoretically, mean that we should be able to automatically validate request and response payloads. However, as of writing there aren't many validators around.
8+
9+
The good news is that there are many validators for JSON Schema for different languages. The bad news is that OpenAPI 3.0 is not entirely compatible with JSON Schema. The Schema Object of OpenAPI 3.0 is an extended subset of JSON Schema Specification Wright Draft 00 with some differences.
10+
11+
The purpose of this project is to fill the grap by doing the conversion between these two formats.
12+
13+
## Features
14+
15+
* converts OpenAPI 3.0 Schema Object to JSON Schema Draft 4
16+
* converts [common named data types](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#data-types) to `type` and `format`
17+
* for example `type: "dateTime"` becomes `type: "string"` with `format: "date-time"`
18+
* deletes `nullable` and adds `"null"` to `type` array if `nullable` is `true`
19+
* supports deep structures with nested `allOf`s etc.
20+
* removes [OpenAPI specific properties](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#fixed-fields-20) such as `discriminator`, `deprecated` etc.
21+
22+
**NOTE**: `$ref`s are not dereferenced. Use a dereferences such as [json-schema-ref-parser](https://www.npmjs.com/package/json-schema-ref-parser) prior to using this package.
23+
24+
## Installation
25+
26+
```
27+
npm install --save openapi-schema-to-json-schema
28+
```
29+
30+
## Usage
31+
32+
Here's a small example to get the idea:
33+
34+
```js
35+
36+
var toJsonSchema = require('openapi-schema-to-json-schema');
37+
38+
var schema = {
39+
type: 'dateTime',
40+
nullable: true
41+
};
42+
43+
var convertedSchema = toJsonSchema(schema);
44+
45+
console.log(convertedSchema);
46+
```
47+
48+
The example prints out
49+
50+
```js
51+
{
52+
type: ['string', 'null'],
53+
format: 'date-time',
54+
'$schema': 'http://json-schema.org/draft-04/schema#'
55+
}
56+
```
57+
58+
Provide the function the schema object with possible options.
59+
60+
### Options
61+
62+
The function accepts `options` object as the second argument. Currently, the following options are supported:
63+
* `cloneSchema` (boolean)
64+
* If set to `false`, converts the provided schema in place. If `true`, clones the schema by converting it to JSON and back. The overhead of the cloning is usually negligible. Defaults to `true`.
65+
* `dateToDateTime` (boolean)
66+
* This is `false` by default and leaves `date` type/format as is. If set to `true`, sets `type: "string"` and `format: "date-time"` if
67+
* `type: "string"` AND `format: "date"` OR
68+
* `type: "date"`
69+
* For example
70+
71+
```js
72+
var schema = {
73+
type: 'date',
74+
};
75+
76+
var convertedSchema = toJsonSchema(schema, {dateToDateTime: true});
77+
78+
console.log(convertedSchema);
79+
```
80+
81+
prints
82+
83+
```js
84+
{
85+
type: 'string',
86+
format: 'date-time',
87+
'$schema': 'http://json-schema.org/draft-04/schema#'
88+
}
89+
```

index.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
module.exports = convert;
2+
3+
function convert(schema, options) {
4+
options = options || {};
5+
options.dateToDateTime = options.dateToDateTime || false;
6+
options.cloneSchema = options.cloneSchema == false ? false : true;
7+
8+
options._structs = ['allOf', 'anyOf', 'oneOf', 'not', 'items', 'additionalProperties'];
9+
options._notSupported = [
10+
'nullable', 'discriminator', 'readOnly',
11+
'writeOnly', 'xml', 'externalDocs',
12+
'example', 'deprecated'
13+
];
14+
15+
if (options.cloneSchema) {
16+
schema = JSON.parse(JSON.stringify(schema));
17+
}
18+
19+
schema = convertSchema(schema, options);
20+
schema['$schema'] = 'http://json-schema.org/draft-04/schema#';
21+
22+
return schema;
23+
}
24+
25+
function convertSchema(schema, options) {
26+
var arrays = options._structs
27+
, notSupported = options._notSupported
28+
, i = 0
29+
, j = 0
30+
, arr = null
31+
;
32+
33+
for (i; i < arrays.length; i++) {
34+
arr = arrays[i];
35+
36+
if (Array.isArray(schema[arr])) {
37+
for (j; j < schema[arr].length; j++) {
38+
schema[arr][j] = convertSchema(schema[arr][j], options);
39+
}
40+
} else if (typeof schema[arr] === 'object') {
41+
schema[arr] = convertSchema(schema[arr], options);
42+
}
43+
}
44+
45+
if (typeof schema.properties === 'object') {
46+
schema.properties = convertProperties(schema.properties, options);
47+
}
48+
49+
schema = convertTypes(schema, options);
50+
51+
for (i=0; i < notSupported.length; i++) {
52+
delete schema[notSupported[i]];
53+
}
54+
55+
return schema;
56+
}
57+
58+
function convertProperties(properties, options) {
59+
var key;
60+
61+
for (key in properties) {
62+
properties[key] = convertSchema(properties[key], options);
63+
}
64+
65+
return properties;
66+
}
67+
68+
function convertTypes(schema, options) {
69+
var newType
70+
, newFormat
71+
, toDateTime = options.dateToDateTime
72+
;
73+
74+
if (schema.type === undefined) {
75+
return schema;
76+
}
77+
78+
if (schema.type == 'string' && schema.format == 'date' && toDateTime === true) {
79+
schema.format = 'date-time';
80+
}
81+
82+
switch(schema.type) {
83+
case 'integer':
84+
newType = 'integer';
85+
break;
86+
case 'long':
87+
newType = 'integer';
88+
newFormat = 'int64';
89+
break;
90+
case 'float':
91+
newType = 'number';
92+
newFormat = 'float';
93+
break;
94+
case 'double':
95+
newType = 'number';
96+
newFormat = 'double';
97+
break;
98+
case 'byte':
99+
newType = 'string';
100+
newFormat = 'byte';
101+
break;
102+
case 'binary':
103+
newType = 'string';
104+
newFormat = 'binary';
105+
break;
106+
case 'date':
107+
newType = 'string';
108+
newFormat = 'date';
109+
if (toDateTime === true) {
110+
newFormat = 'date-time';
111+
}
112+
break;
113+
case 'dateTime':
114+
newType = 'string';
115+
newFormat = 'date-time';
116+
break;
117+
case 'password':
118+
newType = 'string';
119+
newFormat = 'password';
120+
break;
121+
default:
122+
newType = schema.type;
123+
}
124+
125+
schema.type = newType;
126+
schema.format = typeof newFormat === 'string' ? newFormat : schema.format;
127+
128+
if (! schema.format) {
129+
delete schema.format;
130+
}
131+
132+
if (schema.nullable === true) {
133+
schema.type = [schema.type, 'null'];
134+
}
135+
136+
return schema;
137+
}
138+

0 commit comments

Comments
 (0)