Discriminator Issue
Describe the bug
Under certain conditions involving allOf and discriminator fields, OAS can't be resolved.
Describing this is difficult. It's best understood by looking at the examples and work around below.
To Reproduce
root.yaml
openapi: 3.0.3
info:
title: Test
description: |-
Test
version: 1.2.3
paths:
"/api/test":
get:
summary: Test
operationId: test
description: |-
Test
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
price:
anyOf:
- $ref: "common/components/schemas/currency/CurrencyA.yaml"
- $ref: "common/components/schemas/currency/CurrencyB.yaml"
- $ref: "common/components/schemas/currency/CurrencyC.yaml"
discriminator:
propertyName: currencyType
mapping:
CurrencyA: "common/components/schemas/currency/CurrencyA.yaml"
CurrencyB: "common/components/schemas/currency/CurrencyB.yaml"
CurrencyC: "common/components/schemas/currency/CurrencyC.yaml"
Currency.yaml
title: Currency <X>
allOf:
- $ref: "CurrencyBase.yaml"
CurrencyBase.yaml
title: Currency - Base
type: object
properties:
amount:
type: string
currencyType:
type: string
Applies to the latest version - 4.12.14
Actual behavior When launching the back end application, the following line is shown:
$ref: keywords ignored in schema at path "#"
When making a query to any endpoint, the following error is shown:
{
"message": "can't resolve reference #/paths/~1api~1test/get/responses/200/content/application~1json/schema/properties/price/anyOf/0/allOf/0 from id #"
}
Expected behavior Error free validation.
Examples and context I've investigated a bit to thoroughly understand how this error is occurring. I've found two ways that do not cause an error.
In the root.yaml file above, simply remove the discriminator field (and all child fields) and validation works as expected.
In the root.yaml file above, change the schema of the price object from:
price:
<currenySchemaWithDiscriminator>
to
price:
type: array
items:
<currenySchemaWithDiscriminator>
This seems to be a bug when combining discriminators with references. In https://github.com/cdimascio/express-openapi-validator/blob/master/src/middlewares/parsers/schema.preprocessor.ts#L318 a properties field is added to the schema, even if empty. Then, ajv will detect that you have a object containing a $ref key along with an empty properties key, and trigger this piece of code that generates the said warning:
if (it.schema.$ref && $refKeywords) {
if (it.opts.extendRefs == 'fail') {
throw new Error('$ref: validation keywords used in schema at path "' + it.errSchemaPath + '" (see option extendRefs)');
} else if (it.opts.extendRefs !== true) {
$refKeywords = false;
it.logger.warn('$ref: keywords ignored in schema at path "' + it.errSchemaPath + '"');
}
}
I have created a PR to fix this: https://github.com/cdimascio/express-openapi-validator/pull/651