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