Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 035a16f

Browse files
author
Phil Sturgeon
authored
Merge pull request #8 from wework/json-schema-walker
Use JSON Schema Walker
2 parents 8e72209 + 6b8ac3e commit 035a16f

File tree

7 files changed

+163
-94
lines changed

7 files changed

+163
-94
lines changed

‎.circleci/config.yml‎

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
version: 2
2+
shared: &shared
3+
docker:
4+
- image: circleci/node:latest
5+
steps:
6+
- checkout
7+
- restore_cache:
8+
key: dependency-cache-{{ checksum "package.json" }}
9+
- run:
10+
name: Update npm
11+
command: 'sudo npm install -g npm@latest'
12+
- run:
13+
name: Install npm dependencies
14+
command: npm install
15+
- save_cache:
16+
key: dependency-cache-{{ checksum "package.json" }}
17+
paths:
18+
- node_modules
19+
- run:
20+
name: Tests
21+
command: npm test
22+
# - run:
23+
# name: Report Coverage
24+
# command: npm run coverage
25+
26+
jobs:
27+
node-latest:
28+
<<: *shared
29+
30+
node-10:
31+
docker:
32+
- image: circleci/node:10
33+
<<: *shared
34+
35+
node-9:
36+
docker:
37+
- image: circleci/node:9
38+
<<: *shared
39+
40+
node-8:
41+
docker:
42+
- image: circleci/node:8
43+
<<: *shared
44+
45+
workflows:
46+
version: 2
47+
commit:
48+
jobs:
49+
- node-latest
50+
- node-10
51+
- node-9
52+
- node-8

‎README.md‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# JSON Schema to OpenAPI Schema
1+
# JSON Schema to OpenAPI Schema
22

33
A little NodeJS package to convert JSON Schema to [OpenAPI Schema Objects](https://swagger.io/specification/#schemaObject).
44

@@ -72,11 +72,11 @@ _† Draft v5 is also known as Draft Wright 00, as the drafts are often named af
7272

7373
## TODO
7474

75-
- [ ] Support later JSON Schema drafts through a yet-to-be-released json-schema-migrator package
75+
- [ ] Support later JSON Schema drafts via [cloudflare/json-schema-transformer] when it adds that functionality
7676

7777
## Converting Back
7878

79-
To convert the other way, check out [openapi-schema-to-json-schema](https://github.com/mikunn/openapi-schema-to-json-schema), which this package was based on.
79+
To convert the other way, check out [openapi-schema-to-json-schema], which this package was based on.
8080

8181
**NOTE**: `$ref`s are not dereferenced. Use a dereferencer such as [json-schema-ref-parser](https://www.npmjs.com/package/json-schema-ref-parser) prior to using this package.
8282

@@ -98,3 +98,5 @@ npm test
9898
[mikunn]: https://github.com/mikunn
9999
[Phil Sturgeon]: https://github.com/philsturgeon
100100
[openapi-schema-to-json-schema]: https://github.com/mikunn/openapi-schema-to-json-schema
101+
[link-contributors]: https://github.com/wework/json-schema-to-openapi-schema/graphs/contributors
102+
[cloudflare/json-schema-transformer]: https://github.com/cloudflare/json-schema-tools/blob/master/workspaces/json-schema-transform/README.md

‎index.js‎

Lines changed: 31 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const structs = ['allOf','anyOf','oneOf','not','items','additionalProperties'];
1+
const schemaWalker = require('@cloudflare/json-schema-walker');
22

33
function InvalidTypeError(message) {
44
this.name = 'InvalidTypeError';
@@ -7,61 +7,27 @@ function InvalidTypeError(message) {
77

88
InvalidTypeError.prototype = new Error();
99

10-
function convert(schema, options) {
11-
options = options || {};
12-
options.cloneSchema = ! (options.cloneSchema === false);
10+
function convert(schema, options = {}) {
11+
const { cloneSchema = true } = options;
1312

14-
if (options.cloneSchema) {
13+
if (cloneSchema) {
1514
schema = JSON.parse(JSON.stringify(schema));
1615
}
1716

18-
schema = removeRootKeywords(schema);
19-
schema = convertSchema(schema);
20-
17+
const vocab = schemaWalker.getVocabulary(schema, schemaWalker.vocabularies.DRAFT_04);
18+
schemaWalker.schemaWalk(schema, convertSchema, null, vocab);
2119
return schema;
2220
}
2321

24-
function removeRootKeywords(schema) {
22+
function stripIllegalKeywords(schema) {
2523
delete schema['$schema'];
24+
delete schema['$id'];
2625
delete schema['id'];
2726
return schema;
2827
}
2928

30-
function convertSchema(schema) {
31-
let i = 0;
32-
let j = 0;
33-
let struct = null;
34-
35-
for (i; i < structs.length; i++) {
36-
struct = structs[i];
37-
38-
if (Array.isArray(schema[struct])) {
39-
for (j; j < schema[struct].length; j++) {
40-
schema[struct][j] = convertSchema(schema[struct][j]);
41-
}
42-
} else if (typeof schema[struct] === 'object') {
43-
schema[struct] = convertSchema(schema[struct]);
44-
}
45-
}
46-
47-
if (typeof schema.properties === 'object') {
48-
schema.properties = convertProperties(schema.properties);
49-
50-
if (Array.isArray(schema.required)) {
51-
schema.required = cleanRequired(schema.required, schema.properties);
52-
53-
if (schema.required.length === 0) {
54-
delete schema.required;
55-
}
56-
}
57-
if (Object.keys(schema.properties).length === 0) {
58-
delete schema.properties;
59-
}
60-
61-
}
62-
63-
validateType(schema.type);
64-
29+
function convertSchema(schema, path, parent, parentPath) {
30+
schema = stripIllegalKeywords(schema);
6531
schema = convertTypes(schema);
6632
schema = convertDependencies(schema);
6733

@@ -81,19 +47,6 @@ function validateType(type) {
8147
});
8248
}
8349

84-
function convertProperties(properties) {
85-
let key = {};
86-
let property = {};
87-
let props = {};
88-
89-
for (key in properties) {
90-
property = properties[key];
91-
props[key] = convertSchema(property);
92-
}
93-
94-
return props;
95-
}
96-
9750
function convertDependencies(schema) {
9851
const deps = schema.dependencies;
9952
if (typeof deps !== 'object') {
@@ -140,38 +93,40 @@ function convertDependencies(schema) {
14093
}
14194

14295
function convertTypes(schema) {
143-
var newType;
144-
14596
if (schema.type === undefined) {
14697
return schema;
14798
}
14899

149-
// type needs to be a string, not an array
150-
if (schema.type instanceof Array && schema.type.includes('null')) {
151-
var numTypes = schema.type.length;
100+
validateType(schema.type);
152101

153-
schema.nullable=true;
102+
if(Array.isArray(schema.type)){
154103

155-
// if it was just type: ['null'] for some reason
156-
switch (numTypes) {
157-
case 1:
158-
// Didn't know what else to do
159-
newType = 'string';
104+
if (schema.type.length > 2 || !schema.type.includes('null')) {
105+
throw new Error('Type of ' + schema.type.join(',') + ' is too confusing for OpenAPI to understand. Found in ' + JSON.stringify(schema));
106+
}
107+
108+
switch (schema.type.length) {
109+
case 0:
110+
delete schema.type;
160111
break;
161112

162-
case 2:
163-
newType = schema.type.find(function(element) {
164-
return element !== 'null';
165-
});
113+
case 1:
114+
if (schema.type === 'null') {
115+
schema.nullable = true;
116+
}
117+
else {
118+
schema.type = schema.type[0];
119+
}
166120
break;
167121

168122
default:
169-
throw 'type cannot be an array, and you have ' + numTypes + ' types';
123+
schema.type = schema.type.find(type => type !== 'null');
124+
schema.nullable = true;
170125
}
171126
}
172-
173-
if(newType){
174-
schema.type = newType;
127+
elseif(schema.type==='null'){
128+
deleteschema.type;
129+
schema.nullable = true;
175130
}
176131

177132
return schema;
@@ -185,19 +140,4 @@ function convertPatternProperties(schema) {
185140
return schema;
186141
}
187142

188-
function cleanRequired(required, properties) {
189-
var i = 0;
190-
191-
required = required || [];
192-
properties = properties || {};
193-
194-
for (i; i < required.length; i++) {
195-
if (properties[required[i]] === undefined) {
196-
required.splice(i, 1);
197-
}
198-
}
199-
200-
return required;
201-
}
202-
203143
module.exports = convert;

‎package-lock.json‎

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,8 @@
1515
"mocha": "^5.0.0",
1616
"nyc": "^11.6.0",
1717
"should": "^13.2.0"
18+
},
19+
"dependencies": {
20+
"@cloudflare/json-schema-walker": "^0.1.1"
1821
}
1922
}

‎test/nullable.test.js‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,26 @@ it('adds `nullable: true` for `type: [string, null]`', () => {
1717
});
1818
});
1919

20+
21+
it('supports nullables inside sub-schemas', () => {
22+
const schema = {
23+
$schema: 'http://json-schema.org/draft-04/schema#',
24+
oneOf: [
25+
{ type: 'string' },
26+
{ type: 'null' }
27+
]
28+
};
29+
30+
const result = convert(schema);
31+
32+
should(result).deepEqual({
33+
oneOf: [
34+
{ type: 'string' },
35+
{ nullable: true }
36+
]
37+
});
38+
});
39+
2040
it('does not add nullable for non null types', () => {
2141
const schema = {
2242
$schema: 'http://json-schema.org/draft-04/schema#',

‎test/subschema.test.js‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
'use strict';
2+
3+
const convert = require('../');
4+
const should = require('should');
5+
6+
it('strips $id from all subschemas not just root`', () => {
7+
const schema = {
8+
$id: "https://foo/bla",
9+
$schema: "http://json-schema.org/draft-06/schema#",
10+
type: "object",
11+
properties: {
12+
foo: {
13+
$id: "/properties/foo",
14+
type: "array",
15+
items: {
16+
$id: "/properties/foo/items",
17+
type: "object",
18+
properties: {
19+
id: {
20+
$id: "/properties/foo/items/properties/id",
21+
type: "string",
22+
}
23+
}
24+
}
25+
}
26+
}
27+
};
28+
29+
const result = convert(schema);
30+
31+
should(result).deepEqual({
32+
type: "object",
33+
properties: {
34+
foo: {
35+
type: "array",
36+
items: {
37+
type: "object",
38+
properties: {
39+
id: {
40+
type: "string",
41+
}
42+
}
43+
}
44+
}
45+
}
46+
});
47+
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /