Last active
June 12, 2019 07:36
-
-
Save handrews/6dfebd56ef97328f9e4dc7a47a1e8bc7 to your computer and use it in GitHub Desktop.
OAS 3.0 JSON Schema from PR #1270 rewritten with JSON Schema draft-08 proposals
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$id: 'https://openapis.org/schemas/oas/3.0' | |
$schema: 'http://json-schema.org/draft-08-work-in-progress/schema#' | |
type: object | |
required: | |
- openapi | |
- info | |
- paths | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
openapi: | |
type: string | |
pattern: ^3\.0\.\d(-.+)?$ | |
info: | |
$ref: '#Info' | |
externalDocs: | |
$ref: '#ExternalDocumentation' | |
servers: | |
type: array | |
items: | |
$ref: '#Server' | |
security: | |
type: array | |
items: | |
$ref: '#SecurityRequirement' | |
tags: | |
type: array | |
items: | |
$ref: '#Tag' | |
paths: | |
$ref: '#Paths' | |
components: | |
$ref: '#Components' | |
unevaluatedProperties: false | |
$defs: | |
Mixins: | |
$defs: | |
Describable: | |
properties: | |
description: | |
type: string | |
Requireable: | |
properties: | |
required: | |
type: boolean | |
default: false | |
Deprecatable: | |
properties: | |
deprecated: | |
type: boolean | |
default: false | |
DescReqDep: | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Describable' | |
- $ref: '#/$defs/Mixins/$defs/Requireable' | |
- $ref: '#/$defs/Mixins/$defs/Deprecatable' | |
Extensible: | |
patternProperties: | |
'^x-': true | |
WithSingleExample: | |
properties: | |
example: true | |
examples: false | |
WithExampleObjects: | |
properties: | |
example: false | |
examples: | |
type: object | |
additionalProperties: | |
$ref: '#Example' | |
WithExamples: | |
oneOf: | |
- $ref: '#/$defs/Mixins/$defs/WithSingleExample' | |
- $ref: '#/$defs/Mixins/$defs/WithExampleObjects' | |
WithSchema: | |
properties: | |
schema: | |
$ref: '#Schema' | |
content: false | |
WithSchemaAndExamples: | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/WithSchema' | |
- $ref: '#/$defs/Mixins/$defs/WithExamples' | |
WithContent: | |
properties: | |
schema: false | |
content: | |
type: object | |
additionalProperties: | |
$ref: '#MediaType' | |
minProperties: 1 | |
maxProperties: 1 | |
WithNameAndLocation: | |
required: | |
- name | |
- in | |
properties: | |
name: | |
type: string | |
in: | |
type: string | |
enum: | |
- path | |
- query | |
- header | |
- cookie | |
WithExplodeAndReserved: | |
properties: | |
explode: | |
type: boolean | |
allowReserved: | |
type: boolean | |
default: false | |
WithEmpty: | |
properties: | |
allowEmptyValue: | |
type: boolean | |
default: false | |
WithExplodeReservedAndEmpty: | |
allOf: | |
- $refs: '#/$defs/Mixins/$defs/WithExplodeAndReserved' | |
- $refs: '#/$defs/Mixins/$defs/WithEmpty' | |
StyledSimple: | |
allOf: | |
- $refs: '#/$defs/Mixins/$defs/WithExplodeReservedAndEmpty' | |
properties: | |
style: | |
type: string | |
const: simple | |
default: simple | |
StyledMatrix: | |
properties: | |
style: | |
type: string | |
enum: | |
- matrix | |
- label | |
- simple | |
default: simple | |
StyledFormOnly: | |
allOf: | |
- $refs: '#/$defs/Mixins/$defs/WithExplodeReservedAndEmpty' | |
properties: | |
style: | |
type: string | |
const: form | |
default: form | |
StyledFormComplexNoDefaultOrEmpty: | |
allOf: | |
- $refs: '#/$defs/Mixins/$defs/WithExplodeAndReserved' | |
properties: | |
style: | |
type: string | |
enum: | |
- form | |
- spaceDelimited | |
- pipeDelimited | |
- deepObject | |
StyledFormComplex: | |
allOf: | |
- $refs: '#/$defs/Mixins/$defs/StyledFormComplexNoDefaultOrEmpty' | |
- $refs: '#/$defs/Mixins/$defs/WithExplodeReservedAndEmpty' | |
properties: | |
style: | |
default: form | |
Objects: | |
$defs: | |
Reference: | |
$id: '#Reference' | |
type: object | |
required: | |
- $ref | |
properties: | |
$ref: | |
type: string | |
format: uri-reference | |
Info: | |
type: object | |
required: | |
- title | |
- version | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Describable' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
title: | |
type: string | |
termsOfService: | |
type: string | |
format: uri-reference | |
contact: | |
$ref: '#Contact' | |
license: | |
$ref: '#License' | |
$defs: | |
Contact: | |
$id: '#Contact' | |
type: object | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
name: | |
type: string | |
url: | |
type: string | |
format: uri-reference | |
email: | |
type: string | |
format: email | |
unevaluatedProperties: false | |
License: | |
$id: '#License' | |
type: object | |
required: | |
- name | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
name: | |
type: string | |
url: | |
type: string | |
format: uri-reference | |
unevaluatedProperties: false | |
Server: | |
$id: '#Server' | |
type: object | |
required: | |
- url | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Describable' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
url: | |
type: string | |
variables: | |
type: object | |
additionalProperties: | |
type: object | |
required: | |
- default | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Describable' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
enum: | |
type: array | |
items: | |
type: string | |
default: | |
type: string | |
unevaluatedProperties: false | |
unevaluatedProperties: false | |
Response: | |
$id: '#Response' | |
oneOf: | |
- $ref: '#Reference' | |
- type: object | |
required: | |
- description | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Describable' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
headers: | |
type: object | |
additionalProperties: | |
$ref: '#Header' | |
content: | |
type: object | |
additionalProperties: | |
$ref: '#MediaType' | |
links: | |
type: object | |
additionalProperteis: | |
$ref: '#Link' | |
unevaluatedProperties: false | |
MediaType: | |
$id: '#MediaType' | |
type: object | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/WithSchemaAndExamples' | |
properties: | |
encoding: | |
type: object | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/StyledFormComplexNoDefaultOrEmpty' | |
properties: | |
contentType: | |
type: string | |
headers: | |
type: object | |
additionalProperties: | |
$ref: '#Header' | |
unevaluatedProperties: false | |
Example: | |
$id: '#Example' | |
oneOf: | |
- $ref: '#Reference' | |
- type: object | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Describable' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
summary: | |
type: string | |
value: true | |
externalValue: | |
type: string | |
format: uri-reference | |
unevaluatedProperties: false | |
Header: | |
$id: '#Header' | |
oneOf: | |
- $ref: '#Reference' | |
- type: object | |
required: | |
- schema | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/DescReqDep' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
oneOf: | |
- allOf: | |
- $ref: '#/$defs/Mixins/$defs/WithSchemaAndExamples' | |
- $ref: '#/$defs/Mixins/$defs/StyledSimple' | |
- allOf: | |
- $ref: '#/$defs/Mixins/$defs/WithContent' | |
- $ref: '#/$defs/Mixins/$defs/WithEmpty' | |
unevaluatedProperties: false | |
Paths: | |
$id: '#Paths' | |
type: object | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
patternProperties: | |
'^\/': | |
type: object | |
patternProperties: | |
'^(get|put|post|delete|options|head|patch|trace)$': | |
$ref: '#Operation' | |
properties: | |
servers: | |
type: array | |
items: | |
$ref: 'Server' | |
parameters: | |
type: array | |
items: | |
$ | |
unevaluatedProperties: false | |
Operation: | |
$id: '#Operation' | |
type: object | |
required: | |
- responses | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Describable' | |
- $ref: '#/$defs/Mixins/$defs/Deprecatable' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
tags: | |
type: array | |
items: | |
type: string | |
summary: | |
type: string | |
externalDocs: | |
$ref: '#ExternalDocumentation' | |
operationId: | |
type: string | |
parameters: | |
type: array | |
items: | |
$ref: '#Parameter' | |
requestBody: | |
$ref: '#RequestBody' | |
responses: | |
$ref: '#Responses' | |
callback: | |
$ref: '#Callback' | |
security: | |
type: array | |
items: | |
$ref: '#SecurityRequirement' | |
servers: | |
type: array | |
items: | |
$ref: '#Server' | |
unevaluatedProperties: false | |
Responses: | |
$id: '#Responses' | |
type: object | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
default: | |
$ref: '#Response' | |
patternProperties: | |
'[1-5](?:\d{2}|XX)': | |
$ref: '#Response' | |
minProperties: 1 | |
unevaluatedProperties: false | |
SecurityRequirement: | |
$id: '#SecurityRequirement' | |
type: object | |
additionalProperties: | |
type: array | |
items: | |
type: string | |
Tag: | |
$id: '#Tag' | |
type: object | |
required: | |
- name | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Describable' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
name: | |
type: string | |
externalDocs: | |
$ref: '#ExternalDocumentation' | |
unevaluatedProperties: false | |
Parameter: | |
$id: '#Parameter' | |
oneOf: | |
- $ref: '#Reference' | |
- type: object | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/WithNameAndLocation' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
- oneOf: | |
- allOf: | |
- $ref: '#PathParam' | |
- $ref: '#/$defs/Mixins/$defs/Describable' | |
- $ref: '#/$defs/Mixins/$defs/Deprecatable' | |
- required: | |
- required | |
properties: | |
required: | |
const: true | |
default: true | |
- allOf: | |
- anyOf: | |
- $ref: '#QueryParam' | |
- $ref: '#HeaderParam' | |
- $ref: '#CookieParam' | |
- $ref: '#/$defs/Mixins/$defs/DescReqDep' | |
oneOf: | |
- allOf: | |
- required: | |
- schema | |
- $ref: '#/$defs/Mixins/$defs/WithSchemaAndExamples' | |
- oneOf: | |
- allOf: | |
- $ref: '#PathParam' | |
- $ref: '#/$defs/Mixins/$defs/StyledMatrix' | |
- allOf: | |
- $refs: '#QueryParam' | |
- $refs: '#/$defs/Mixins/$defs/StyledFormComplex' | |
- allOf: | |
- $ref: '#HeaderParam' | |
- $ref: '#/$defs/Mixins/$defs/StyledSimple' | |
- allOf: | |
- $ref: '#CookieParam' | |
- $refs: '#/$defs/Mixins/$defs/StyledFormOnly' | |
- allOf: | |
- required: | |
- content | |
- $ref: '#/$defs/Mixins/$defs/WithContent' | |
- $ref: '#/$defs/Mixins/$defs/WithEmpty' | |
unevaluatedProperties: false | |
$defs: | |
PathParam: | |
$id: '#PathParam' | |
properties: | |
in: | |
const: path | |
QueryParam: | |
$id: '#QueryParam' | |
properties: | |
in: | |
const: query | |
HeaderParam: | |
$id: '#HeaderParam' | |
properties: | |
in: | |
const: header | |
CookieParam: | |
$id: '#CookieParam' | |
properties: | |
in: | |
const: cookie | |
RequestBody: | |
$id: '#RequestBody' | |
required: | |
- content | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Describable' | |
- $ref: '#/$defs/Mixins/$defs/Requireable' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
content: | |
type: object | |
additionalProperties: | |
$ref: '#MediaType' | |
unevaluatedProperties: false | |
SecurityScheme: | |
$id: '#SecurityScheme' | |
oneOf: | |
- $ref: '#Reference' | |
- type: object | |
required: | |
-type | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Describable' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
type: | |
string: | |
enum: | |
- apiKey | |
- http | |
- bearer | |
- oauth2 | |
- openIdConnect | |
oneOf: | |
- $ref: '#APIKey' | |
- $ref: '#HTTP' | |
- $ref: '#OAuth2' | |
- $ref: '#OpenIdConnect' | |
unevaluatedProperties: false | |
$defs: | |
APIKey: | |
$id: '#APIKey' | |
properties: | |
type: | |
const: apiKey | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/WithNameAndLocation' | |
not: | |
$ref: '#PathParam' | |
HTTP: | |
$id: '#HTTP' | |
required: | |
- scheme | |
properties: | |
scheme: | |
type: string | |
oneOf: | |
- properties: | |
type: | |
const: http | |
- properties: | |
type: | |
const: bearer | |
bearerFormat: | |
type: string | |
OAuth2: | |
$id: '#OAuth2' | |
required: | |
- flows | |
properties: | |
type: | |
const: oauth2 | |
flows: | |
$ref: '#OAuthFlows' | |
OpenIdConnect: | |
$id: '#OpenIdConnect' | |
required: | |
- openIdConnectUrl | |
properties: | |
type: | |
const: openIdConnect | |
openIdConnectUrl: | |
type: string | |
format: uri | |
OAuthFlows: | |
$id: '#OAuthFlows' | |
type: object | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
properties: | |
implicit: | |
allOf: | |
- required: | |
- scopes | |
- $ref: '#CommonFlow' | |
- $ref: '#AuthorizationFlow' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
unevaluatedProperties: false | |
password: | |
allOf: | |
- $ref: '#CommonFlow' | |
- $ref: '#TokenFlow' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
unevaluatedProperties: false | |
clientCredentials: | |
allOf: | |
- $ref: '#CommonFlow' | |
- $ref: '#TokenFlow' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
unevaluatedProperties: false | |
authorizationCode: | |
allOf: | |
- $ref: '#CommonFlow' | |
- $ref: '#TokenFlow' | |
- $ref: '#AuthorizationFlow' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
unevaluatedProperties: false | |
unevaluatedProperties: false | |
$defs: | |
Common: | |
$id: '#CommonFlow' | |
properties: | |
refreshUrl: | |
type: string | |
format: uri-reference | |
scopes: | |
type: object | |
additionalProperties: | |
type: string | |
Token: | |
$id: '#TokenFlow' | |
required: | |
- tokenUrl | |
properties: | |
tokenUrl: | |
type: string | |
format: uri-reference | |
Authorization: | |
$id: '#AuthorizationFlow' | |
required: | |
- authorizationUrl | |
properties: | |
authorizationUrl: | |
type: string | |
format: uri-reference | |
Link: | |
$id: '#Link' | |
oneOf: | |
- $ref: '#Reference' | |
- type: object | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Describable' | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
oneOf: | |
- properties: | |
operationRef: | |
type: string | |
format: uri-reference | |
operationId: false | |
- properties: | |
operationRef: false | |
operationId: | |
type: string | |
properties: | |
parameters: | |
type: object | |
additionalProperties: true | |
requestBody: true | |
server: | |
$ref: '#Server' | |
unevaluatedProperties: false | |
Callback: | |
$id: '#Callback' | |
oneOf: | |
- $ref: '#Reference' | |
- type: object | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
unevaluatedProperties: false | |
Schema: | |
$id: '#Schema' | |
oneOf: | |
- $ref: '#Reference' | |
- type: object | |
allOf: | |
- $ref: 'http://json-schema.org/draft-04/schema#' | |
- $ref: '#SchemaRestrictions' | |
- $ref: '#SchemaExtensions' | |
- $ref: '#/$defs/Mixins/$def/Extensible' | |
unevaluatedProperties: false | |
$defs: | |
Restrictions: | |
$id: '#SchemaRestrictions' | |
properties: | |
type: | |
not: | |
const: 'null' | |
not: | |
$ref: '#/$defs/Schema' | |
allOf: | |
type: array | |
items: | |
$ref: '#/$defs/Schema' | |
oneOf: | |
type: array | |
items: | |
$ref: '#/$defs/Schema' | |
anyOf: | |
type: array | |
items: | |
$ref: '#/$defs/Schema' | |
items: | |
$ref: '#/$defs/Schema' | |
properties: | |
type: object | |
additionalProperties: | |
$ref: '#/$defs/Schema' | |
additionalProperties: | |
oneOf: | |
- $ref: '#/$defs/Schema' | |
- type: boolean | |
default: true | |
patternProperties: false | |
Extensions: | |
$id: '#SchemaExtensions' | |
properties: | |
nullable: | |
type: boolean | |
default: false | |
discriminator: | |
$ref: '#Discriminator' | |
readOnly: | |
type: boolean | |
default: false | |
writeOnly: | |
type: boolean | |
default: false | |
example: true | |
externalDocs: | |
$ref: '#ExternalDocumentation' | |
deprecated: | |
type: boolean | |
default: false | |
xml: | |
$ref: '#XML' | |
Discriminator: | |
$id: '#Discriminator' | |
type: object | |
required: | |
- propertyName | |
properties: | |
propertyName: | |
type: string | |
mapping: | |
type: object | |
additionalProperties: | |
type: string | |
XML: | |
$id: '#XML' | |
type: object | |
properties: | |
name: | |
type: string | |
namespace: | |
type: string | |
format: url | |
prefix: | |
type: string | |
attribute: | |
type: boolean | |
default: false | |
wrapped: | |
type: boolean | |
default: false | |
patternProperties: | |
'^x-': true | |
additionalProperties: false | |
Components: | |
$id: '#Components' | |
type: object | |
allOf: | |
- $ref: '#/$defs/Mixins/$defs/Extensible' | |
- additionalProperties: | |
$comment: All sub-objects have the same property name constraints | |
type: object | |
propertyNames: | |
pattern: '^[a-zA-Z0-9\.\-_]+$' | |
properties: | |
schemas: | |
additionalProperties: | |
$ref: '#Schema' | |
responses: | |
additionalProperties: | |
$ref: '#Responses' | |
parameters: | |
additionalProperties: | |
$ref: '#Parameter' | |
examples: | |
additionalProperties: | |
$ref: '#Example' | |
requestBodies: | |
additionalProperties: | |
$ref: '#RequestBody' | |
headers: | |
additionalProperties: | |
$ref: '#Header' | |
links: | |
additionalProperties: | |
$ref: '#Link' | |
callbacks: | |
additionalProperties: | |
$ref: '#Callback' | |
unevaluatedProperties: true |
What is the likelihood of unevaluatedProperties
being accepted as the json-schema for OAS 3.0? OAI/OpenAPI-Specification#1032 was accepted last month and does not include unevaluatedProperties
.
@dskvr unevaluatedProperties
is part of the next draft of JSON Schema, so #1032 couldn't make use of it yet.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a refactor of OAI/OpenAPI-Specification#1270 which uses draft-06 and draft-07 features, as well as several draft-08 proposals. It illustrates different things for the JSON Schema and OpenAPI projects.
unevaluatedProperties
, in a complex real-world scenario.unevaluatedProperties
allows us to eliminate the extensive duplication in PR 1270.High level overview
I broke the schema up into two kinds of definitions: mixins and objects. The mixins collect various individual or groups of properties that are re-used in many places. This includes some
oneOf
combinations which are either mutually exclusive due to a pinnedenum
value, or I made them mutually exclusive by forbidding each other's properties by setting the property schemas tofalse
(see Example and Examples for... er... examples :-)While organizing the mixins like this maximizes re-use, it does obscure the structure of things a bit. However, I don't think that schemas should be primary documentation- that's what the spec is for. The schema needs to be correct and maintainable more than it needs to be obvious for less techncial human readers.
Here is a quick guide to the post-draft-04 features used above:
draft-06
const
in place of single-elementenum
true
in place of{}
false
in place of{"not": {}}
$id
instead ofid
$id
plain name fragments$ref
styles, the choice is not otherwise significant herepropertyNames
, a schema applied to all property names in the instancepatternProperties
"format": "uri-reference"
instead ofuriref
draft-07
if
/then
/else
, although some of theoneOf
s could be reworked to use itcontains
or any of the newer formatsdraft-08 proposals
definitions
to$defs
$ref
,$id
, and$schema
as it has no validation effectunevaluatedProperties
gets its own section belowunevaluatedProperties
The
unevaluatedProperties
proposal is key, so let's go through an example of how it works.TL;DR: It does what you probably want
additionalProperties
to do when you put it next toanyOf
,allOf
, oroneOf
.Both of the following schemas successfully validate
{"foo": 1, "common": true}
and{"bar": "hi", "common": false}
, but fail on{"foo": 1, "common": true, "oof" 2}
for different reasons in each schema. Let's take a look at what those different reasons are:In the above schema,
{"foo": 1, "common": true, "oof: 2}
fails because of theadditionalProperties: false
adjacent to the definition of "foo". It prevents "off", and any other property but "foo" or "common", from validating.However, note that
common: {type: boolean}
is duplicated in the two branches of theanyOf
. This is becauseadditionalProperties
only "sees"properties
andpatternProperties
that are defined immediately adjacent to it in the same schema object. This is also whyadditionalProperties: false
is duplicated. IfadditionalProperties
were outside of theanyOf
, it would not have any immediately adjacentproperties
orpatternProperties
so any object with any properties would fail validation.One benefit of the way
additionalProperties
is defined is that you can compute the set of property names to which it applies statically from the schema alone, without evaluating an instance.Now let's look at it with
unevaluatedProperties
:Here we see
common
defined once at the top level, alongside a top levelunevaluatedProperties: false
which replaces the two separate uses ofadditionalProperties: false
.unevaluatedProperties
can "see" into theanyOf
, because it applies to any property that has not successfully validated against any subschema of any keyword adjacent to it.In this example, the
anyOf
and the outerproperties
are both adjacent tounevaluatedProperties
. When validating{"foo": 1, "common": true}
, "common" is successfully evaluated against a subschema of the adjacentproperties
, and "foo" is successfully evaluated against a subschema under theanyOf
.However, when validating
{"foo": 1, "common": true, "oof": 2}
"oof" has not been validated against any defined subschema, so it is considered to be unevaluated. And since we have set
unevaluatedProperties
tofalse
, its presence causes validation to fail.Considering a more complex
anyOf
:With this schema,
{"bar": "hi", "common": false, "oof": 2}
is valid, while{"foo": 1, "common": true, "oof": 2}
is not. This shows howunevaluatedProperties
is dynamic in nature.When the first instance matches the subschema with "bar", it causes "bar" and "oof" to be evaluated. And "common" is still evaluated by the top-level
properties
. Therefore there are no unevaluated properties in the instance and validation passes.The second instance fails the "bar" branch of the
anyOf
. This means that "oof" is not considered to have been evaluated. Even though it passes the "oof" subschema in the "bar" branch, since the whole "bar" branch fails validation (because there is no "bar" in the instance), no subschema in the branch contributes to the evaluation count.The second instance only passes the "foo" branch, so only "foo" and "common" are considered to have been evaluated. "oof" has not been, so
unevaluatedProperties: false
causes it to fail.