Skip to content

[WIP] Alternative OAS3 JSON Schema #1270

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 33 commits into from
Apr 18, 2019
Merged
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
45971df
Initial schema commit
webron Jul 14, 2017
bda4218
so many fixes
webron Jul 18, 2017
1eb22f0
items array -> object
webron Jul 18, 2017
bd277c6
A couple more fixes
webron Jul 18, 2017
069367f
Fixed restriction on Server's url
webron Jul 18, 2017
629cd7c
make callbacks great again!
webron Jul 18, 2017
49e784d
fixed servervariable.enum
webron Jul 24, 2017
1087db4
Use "uri-reference", not "url" or "uriref"
handrews Nov 8, 2018
13a4fd2
Fix usage of "not"
handrews Nov 8, 2018
5529143
Use patternProperties for $ref
handrews Nov 8, 2018
82ef49c
XML namespace must be an absolute URI
handrews Nov 15, 2018
f71d7f8
In Daft 5, schema.enum only SHOULD be unique, not MUST
MikeRalphson Nov 20, 2018
e619259
parameters arrays MUST be unique on name & in, therefore MUST be uniq…
MikeRalphson Nov 20, 2018
e9de80f
tags array MUST be unique by name, therefore MUST be unique across al…
MikeRalphson Nov 20, 2018
99226cf
responses object keys pattern must be anchored
MikeRalphson Nov 20, 2018
6fbc926
responses object map MAY be extended with specification extensions
MikeRalphson Nov 20, 2018
0684d65
Response.headers map missing type:object
MikeRalphson Nov 20, 2018
f39cbf0
Merge pull request #1744 from handrews/schema-fixes
Dec 4, 2018
88dd430
Pre-format schema to improve changes relevancy
vearutop Jan 8, 2019
26cf125
Simplify Schema or Reference
vearutop Jan 8, 2019
bedcc17
Combine HTTP Methods in `patternProperties`
vearutop Jan 8, 2019
9592b1f
Define Parameter as a filtered superset
vearutop Jan 8, 2019
81e3dd5
Combine some definitions as filtered supersets
vearutop Jan 8, 2019
cdd7816
Move XOR logic to definitions, remove unused definition NonBearerHTTP…
vearutop Jan 8, 2019
2208e08
Embed references
vearutop Jan 8, 2019
3f09f46
Revert embed references as it flattens definition scopes and therefor…
vearutop Mar 8, 2019
66659e4
Remove temporary README
vearutop Mar 8, 2019
bbd49b6
Revert embedding $ref in Schema
vearutop Mar 22, 2019
c094c22
Merge pull request #1800 from vearutop/oas3-schema
Mar 26, 2019
92e15eb
Add schema metadata
webron Apr 2, 2019
6d17b63
JSON version of the schema
webron Apr 18, 2019
3dcfee1
Added README with basic information
webron Apr 18, 2019
35ab014
Update README.md
Apr 18, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 141 additions & 41 deletions schemas/v3.0/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ required:
properties:
openapi:
type: string
enum:
- 3.0.0
pattern: ^3\.0\.\d(-.+)?$
info:
$ref: '#/definitions/Info'
externalDocs:
Expand All @@ -34,10 +33,12 @@ additionalProperties: false
definitions:
Reference:
type: object
required:
- $ref
properties:
$ref:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should $ref be a required property? Otherwise I get false matches of both halves of a oneOf.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, will fix.

type: string
format: uri-ref
format: uriref
Info:
type: object
required:
Expand All @@ -50,7 +51,7 @@ definitions:
type: string
termsOfService:
type: string
format: uri-ref
format: uriref
contact:
$ref: '#/definitions/Contact'
license:
Expand All @@ -69,7 +70,7 @@ definitions:
type: string
url:
type: string
format: uri-ref
format: uriref
email:
type: string
format: email
Expand All @@ -86,7 +87,7 @@ definitions:
type: string
url:
type: string
format: uri-ref
format: uriref
patternProperties:
'^x-': {}
additionalProperties: false
Expand All @@ -98,7 +99,7 @@ definitions:
properties:
url:
type: string
format: uri-ref
format: uriref
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a uri-template format, but this doesn't exist in JSON schema Draft 5. If we replace format with pattern a suitable regex seems to be (lifted from ajv which quotes https://tools.ietf.org/html/rfc6570)

/^(?:(?:[^\x00-\x20"'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#.\/;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?:\:[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?:\:[1-9][0-9]{0,3}|\*)?)*\})*$/i

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not get into that. I'm not sure what the difference is between uriref and uri-template. If it's too permissive, in this case, I'm ok with it. If it's too constrict, we can drop the format altogether.

I find adding complex regex impossible to read and maintain. We could have added a regex to define media types as well and we didn't (we had a similar discussion about it around 2.0's schema).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. I'm seeing that it's too restrictive being a uriref, not allowing {} characters. Dropping the format seems the best option.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, will remove.

description:
type: string
variables:
Expand Down Expand Up @@ -254,31 +255,57 @@ definitions:
type:
type: string
enum:
- array
- boolean
- integer
- number
- object
- string
- array
- boolean
- integer
- number
- object
- string
Copy link

@brandur brandur Sep 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to get "null" added to this list? We return some properties that are present in a response object, but contain a null value, and we need to have the type null to accurately describe them.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see now that 3.0.0 indicates that it doesn't support the null type.

Do you have any feeling as to whether this is set in stone yet? Unless I'm really misunderstanding something, the trouble with nullable is that it's not in the JSON schema core, and means that we can no longer use off-the-shelf JSON schema validators to validate the schemas that are generated for OpenAPI 3.0.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And alright, I just read through #229.

It doesn't look like the core team can be persuaded on this point, but oof, one of my perceived advantages of the 3.0 upgrade was not having to deal with the arbitrary restrictions that 2.0 imposed on JSON schemas. It seems that there are now fewer of them for 3.0, but they're still there, and JSON schema generated to be OpenAPI-compatible still cannot be used to accurately describe all types of API resources without additional meta-annotations (which are obviously not portable).

I'm not sure where that leaves us.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

V3 leaves us in the position where the Schema object can processed with JSON schema tooling without generating errors (due mainly to type: file). It is true that not everything in JSON schema is supported. Hopefully we can get there in the future.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brandur see also #1389

not:
Copy link
Member

@MikeRalphson MikeRalphson Jul 14, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we also missing definitions for the allOf, oneOf and anyOf arrays?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, added.

$ref: '#/definitions/Schema'
oneOf:
- $ref: '#/definitions/Schema'
- $ref: '#/definitions/Reference'
allOf:
type: array
items:
oneOf:
- $ref: '#/definitions/Schema'
- $ref: '#/definitions/Reference'
oneOf:
type: array
items:
oneOf:
- $ref: '#/definitions/Schema'
- $ref: '#/definitions/Reference'
anyOf:
type: array
items:
oneOf:
- $ref: '#/definitions/Schema'
- $ref: '#/definitions/Reference'
items:
type: array
Copy link
Contributor

@tfesenko tfesenko Jul 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering why array's item type is array and not an object(schema or reference). From the OAS3 spec:

items - Value MUST be an object and not an array. Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. <...>

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's me being too tired. Good catch, will fix shortly.

items:
oneOf:
- $ref: '#/definitions/Schema'
- $ref: '#/definitions/Reference'
properties:
type: object
additionalProperties:
$ref: '#/definitions/Schema'
oneOf:
- $ref: '#/definitions/Schema'
- $ref: '#/definitions/Reference'
additionalProperties:
oneOf:
- $ref: '#/definitions/Schema'
- $ref: '#/definitions/Reference'
- type: boolean
default: true
description:
type: string
format:
type: string
default: {}
$ref:
type: string
format: uri-ref
nullable:
type: boolean
default: false
Expand Down Expand Up @@ -327,7 +354,7 @@ definitions:
attribute:
type: boolean
default: false
wrapperd:
wrapped:
type: boolean
default: false
patternProperties:
Expand Down Expand Up @@ -383,6 +410,8 @@ definitions:

MediaTypeWithExamples:
type: object
required:
- examples
properties:
schema:
oneOf:
Expand All @@ -409,17 +438,28 @@ definitions:
type: string
description:
type: string
value:
type: string
value: {}
externalValue:
type: string
format: uri-ref
format: uriref
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the modern name of a uriref is uri-reference. It might be better to switch over to that in the name of general correctness.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OpenAPI 3.0.0 uses JSON schema Draft Wright 00 (aka Draft 5) so uriref is correct, uri-reference is defined in Draft Wright 01 (aka JSON Schema Draft 6).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Mike. I'd seen the change in the changelog, but assumed maybe some tooling was outdated. Do you know what the rational for tying the spec and an older JSON schema version is? I guess because draft 6 introduces quite a few changes?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brandur ...because tying the spec to "whatever is the current version" would be impossible for tooling to deal with. We had to lock on one version.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MikeRalphson it would be better to use uri-reference as formats are extensible. It does not violate Draft 5, and is forward compatible with Draft 6. There are actual Draft 6 validators in the wild (Draft 5 has never been directly implemented, and probably won't be).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@handrews for better or worse, we're stuck with Draft 5 until at least OpenAPI 3.1.0 (or possibly 4.0 if it's deemed a breaking change). I think it would cause more confusion to use formats from Draft 6, and possibly result in those URI Reference properties not being validated at all. At least ajv can be convinced to operate in Draft 5 mode with a little setup. Of course there's no specific reason the schema for OpenAPI 3 has to itself be in Draft 5 just because OpenAPI 3 uses a modified version of Draft 5 internally, but again, it reduces confusion.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MikeRalphson I was under the impression that a lot of people use extended formats with OpenAPI? Most validators that support formats, including Ajv allow registering additional ones.

If this is the only extended (from the draft-05 perspective) format being used, then yes, I agree it makes sense not to use it. But if it's not, I'd encourage folks to ignore uriref and use uri-reference instead, just as they would use byte or password or some other non-standard format.

patternProperties:
'^x-': {}
additionalProperties: false

Header:
oneOf:
- $ref: '#/definitions/HeaderWithSchema'
- $ref: '#/definitions/HeaderWithContent'

HeaderWithSchema:
oneOf:
- $ref: '#/definitions/HeaderWithSchemaWithExample'
- $ref: '#/definitions/HeaderWithSchemaWithExamples'

HeaderWithSchemaWithExample:
type: object
required:
- schema
properties:
description:
type: string
Expand All @@ -439,24 +479,81 @@ definitions:
default: simple
explode:
type: boolean
allowReserved:
type: boolean
default: false
schema:
oneOf:
- $ref: '#/definitions/Schema'
- $ref: '#/definitions/Reference'
example: {}
patternProperties:
'^x-': {}
additionalProperties: false

HeaderWithSchemaWithExamples:
type: object
required:
- schema
- examples
properties:
description:
type: string
required:
type: boolean
default: false
deprecated:
type: boolean
default: false
allowEmptyValue:
type: boolean
default: false
style:
type: string
enum:
- false
- simple
default: simple
explode:
type: boolean
allowReserved:
type: boolean
default: false
schema:
oneOf:
- $ref: '#/definitions/Schema'
- $ref: '#/definitions/Reference'
examples:
type: array
items:
type: object
additionalProperties:
oneOf:
- $ref: '#/definitions/Example'
- $ref: '#/definitions/Reference'
example: {}
patternProperties:
'^x-': {}
additionalProperties: false

HeaderWithContent:
type: object
required:
- content
properties:
description:
type: string
required:
type: boolean
default: false
deprecated:
type: boolean
default: false
allowEmptyValue:
type: boolean
default: false
content:
type: object
additionalProperties:
$ref: '#/definitions/MediaType'
minProperties: 1
maxProperties: 1
patternProperties:
'^x-': {}
additionalProperties: false
Expand Down Expand Up @@ -557,8 +654,6 @@ definitions:
additionalProperties: false

Responses:
allOf:
- $ref: '#/definitions/Extensions'
type: object
properties:
default:
Expand All @@ -577,6 +672,7 @@ definitions:
type: object
patternProperties:
'^x-': {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this requires an additionalProperties: false otherwise responses do match this sub-schema.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@webron @MikeRalphson why is this not: block here? Filtering out other stuff, you have

  Responses:
    type: object
    patternProperties:
      '^x-': {}
    additionalProperties: false
    not:
      type: object
      patternProperties:
        '^x-': {}
      additionalProperties: false

which is an impossible schema. {"type": "object", "not": {"type": "object"}} alone makes it impossible. Any keywords that are the same inside and outside of a not by definition are impossible to satisfy.

Am I misreading something here?

additionalProperties: false


SecurityRequirement:
Expand Down Expand Up @@ -610,7 +706,7 @@ definitions:
type: string
url:
type: string
format: uri-ref
format: uriref
patternProperties:
'^x-': {}
additionalProperties: false
Expand Down Expand Up @@ -825,6 +921,7 @@ definitions:
- in
- schema
- required
- examples
properties:
name:
type: string
Expand Down Expand Up @@ -876,6 +973,7 @@ definitions:
- name
- in
- schema
- examples
properties:
name:
type: string
Expand Down Expand Up @@ -927,6 +1025,7 @@ definitions:
- name
- in
- schema
- examples
properties:
name:
type: string
Expand Down Expand Up @@ -975,6 +1074,7 @@ definitions:
- name
- in
- schema
- examples
properties:
name:
type: string
Expand Down Expand Up @@ -1187,8 +1287,8 @@ definitions:
type: string
type:
type: string
enum:
- http
enum:
- http
description:
type: string
patternProperties:
Expand Down Expand Up @@ -1255,10 +1355,10 @@ definitions:
properties:
authorizationUrl:
type: string
format: uri-ref
format: uriref
refreshUrl:
type: string
format: uri-ref
format: uriref
scopes:
type: object
additionalProperties:
Expand All @@ -1274,10 +1374,10 @@ definitions:
properties:
tokenUrl:
type: string
format: uri-ref
format: uriref
refreshUrl:
type: string
format: uri-ref
format: uriref
scopes:
type: object
additionalProperties:
Expand All @@ -1293,10 +1393,10 @@ definitions:
properties:
tokenUrl:
type: string
format: uri-ref
format: uriref
refreshUrl:
type: string
format: uri-ref
format: uriref
scopes:
type: object
additionalProperties:
Expand All @@ -1313,13 +1413,13 @@ definitions:
properties:
authorizationUrl:
type: string
format: uri-ref
format: uriref
tokenUrl:
type: string
format: uri-ref
format: uriref
refreshUrl:
type: string
format: uri-ref
format: uriref
scopes:
type: object
additionalProperties:
Expand All @@ -1338,7 +1438,7 @@ definitions:
properties:
operationRef:
type: string
format: uri-ref
format: uriref
parameters:
type: object
additionalProperties: {}
Expand Down