1[//]: # (Copyright 2021, Oracle and/or its affiliates.) 2 3## OpenAPI 3.x discriminator support 4 5Starting with `1.0.51`, `json-schema-validator` partly supports the use of the [`discriminator`](https://github.com/OAI/OpenAPI-Specification/blob/7cc8f4c4e742a20687fa65ace54ed32fcb8c6df0/versions/3.1.0.md#discriminator-object) keyword. 6 7Note that the use of the `discriminator` keyword does not affect the validation of `anyOf` or `oneOf`. The use of `discriminator` is not equivalent to having a `if`/`then` with the `discriminator` propertyName. 8 9When a `discriminator` is used, the assertions generated by `anyOf` or `oneOf` will only be the assertions generated from the schema that the discriminator applies to. An assertion will be generated if a `discriminator` is used but there is no matching schema that maps to the value in the `propertyName`. 10 11## How to use 12 131. Configure `SchemaValidatorsConfig` accordingly: 14 ```java 15 class Demo{ 16 void demo() { 17 SchemaValidatorsConfig config = new SchemaValidatorsConfig(); 18 config.setOpenAPI3StyleDiscriminators(true); // defaults to false 19 } 20 } 21 ``` 222. Use the configured `SchemaValidatorsConfig` with the `JsonSchemaFactory` when creating the `JsonSchema` 23 ```java 24 class Demo{ 25 void demo() { 26 SchemaValidatorsConfig config = new SchemaValidatorsConfig(); 27 config.setOpenAPI3StyleDiscriminators(true); // defaults to false 28 JsonSchemaFactory factory = JsonSchemaFactory.getInstance(VersionFlag.V202012); 29 JsonSchema schema = factory.getSchema(schemaURI, schemaJacksonJsonNode, config); 30 } 31 } 32 ``` 333. Ensure that the type field that you want to use as discriminator `propertyName` is required in your schema 34 35## Scope of Support 36 37Discriminators are unfortunately somewhat vague in their definition, especially in regard to JSON Schema validation. So, only 38those parts that are indisputable are considered at this moment. 39 40### Supported: 41 42* Polymorphism using `allOf` and `anyOf` with implicit and explicit `mapping` 43* `discriminator` on base types and types derived 44 thereof `A(with base discriminator) -> B(with optional additive discriminator) -> C(with optional additive discriminator)` 45 46### Not supported: 47 48* `propertyName` redefinition is prohibited on additive discriminators 49* `mapping` key redefinition is also prohibited on additive discriminators 50* the specification indicates that inline properties should be ignored. 51 So, this example would respect `foo` 52 ```yaml 53 allOf: 54 - $ref: otherSchema 55 - type: object 56 properties: 57 foo: 58 type: string 59 required: ["foo"] 60 ``` 61 while 62 ```yaml 63 properties: 64 foo: 65 type: string 66 required: ["foo"] 67 allOf: 68 - $ref: otherSchema 69 ``` 70 should ignore `foo`. **Ignoring `foo` in the second example is currently not implemented** 71* You won't get a warning if your `discriminator` uses a field for `propertyName` that is not `required` 72 73## Schema Examples 74 75More examples in https://github.com/networknt/json-schema-validator/blob/master/src/test/resources/openapi3/discriminator.json 76 77### Base type and extended type (the `anyOf` forward references are required) 78 79#### Example: 80 81```json 82{ 83 "anyOf": [ 84 { 85 "$ref": "#/components/schemas/Room" 86 }, 87 { 88 "$ref": "#/components/schemas/BedRoom" 89 } 90 ], 91 "components": { 92 "schemas": { 93 "Room": { 94 "type": "object", 95 "properties": { 96 "@type": { 97 "type": "string" 98 }, 99 "floor": { 100 "type": "integer" 101 } 102 }, 103 "required": [ 104 "@type" 105 ], 106 "discriminator": { 107 "propertyName": "@type" 108 } 109 }, 110 "BedRoom": { 111 "type": "object", 112 "allOf": [ 113 { 114 "$ref": "#/components/schemas/Room" 115 }, 116 { 117 "type": "object", 118 "properties": { 119 "numberOfBeds": { 120 "type": "integer" 121 } 122 }, 123 "required": [ 124 "numberOfBeds" 125 ] 126 } 127 ] 128 } 129 } 130 } 131} 132``` 133 134#### Here the default mapping key for `BedRoom` is overridden with `bed` from `Room` 135 136```json 137{ 138 "anyOf": [ 139 { 140 "$ref": "#/components/schemas/Room" 141 }, 142 { 143 "$ref": "#/components/schemas/BedRoom" 144 } 145 ], 146 "components": { 147 "schemas": { 148 "Room": { 149 "type": "object", 150 "properties": { 151 "@type": { 152 "type": "string" 153 }, 154 "floor": { 155 "type": "integer" 156 } 157 }, 158 "required": [ 159 "@type" 160 ], 161 "discriminator": { 162 "propertyName": "@type", 163 "mapping": { 164 "bed": "#/components/schemas/BedRoom" 165 } 166 } 167 }, 168 "BedRoom": { 169 "type": "object", 170 "allOf": [ 171 { 172 "$ref": "#/components/schemas/Room" 173 }, 174 { 175 "type": "object", 176 "properties": { 177 "numberOfBeds": { 178 "type": "integer" 179 } 180 }, 181 "required": [ 182 "numberOfBeds" 183 ] 184 } 185 ] 186 } 187 } 188 } 189} 190``` 191