openapi-schema-validator icon indicating copy to clipboard operation
openapi-schema-validator copied to clipboard

Issue with OAS 3.1 - unknown keyword: "unevaluatedProperties"?

Open p-bakker opened this issue 7 months ago • 1 comments

Hi,

Not sure if this is a problem with this library, another library or just user error, but I'm getting this error when using openapiGlue and I think I traced it to the AJV validator that I think is contributed by this library: FastifyError [Error]: Failed building the validation schema for GET: /invoices, due to error strict mode: unknown keyword: "unevaluatedProperties"

The relevant part of my OAS spec:

paths:
  /invoices:
    get:
     ....
      parameters:
        - $ref: '#/components/parameters/GenericFilter'
        - ....
components:
  parameters:
    GenericFilter:
      name: typedFilter
      in: query
      required: true
      schema:
        anyOf:
          - type: object
            unevaluatedProperties: {}
          - type: array
            items:
              type: object
              unevaluatedProperties: {}
      explode: false

AFAICT the above is valid OAS 3.1 spec...

Any thoughts?

p-bakker avatar Apr 07 '25 13:04 p-bakker

Hi,

thanks for asking.

The error is generated by Fastify because unevaluatedProperties was only introduced in JSON schema draft-2019-09 (see https://ajv.js.org/json-schema.html#draft-2019-09) and not in JSON schema draft-07 which AJV uses by default (see https://ajv.js.org/json-schema.html#json-schema-versions).

OpenAPI 3.0.4 still refers to JSON Schema Specification Draft Wright-00 aka draft-05 (see https://spec.openapis.org/oas/v3.0.4.html#bib-json-schema-05) but 3.1 specifically refers to draft 2020-12 (see https://spec.openapis.org/oas/v3.1.0.html#bib-json-schema-2020-12)

So the trick is to tell Fastify to use AJV with schema 2020-12 (or 2019-09).

e.g. something like:

import AJV2020 from "ajv/dist/2020.js";
const ajv = new AJV2020({
	removeAdditional: 'all',
	useDefaults: true,
	coerceTypes: 'array',
});
const fastify = Fastify();
fastify.setValidatorCompiler(({ schema, method, url, httpPart }) => {
	return ajv.compile(schema)
})
fastify.register(fastifyOpenapiGlue, opts);

But maybe the better question is: what do you want to achieve with the schema?

Kind regards, Hans

seriousme avatar Apr 07 '25 18:04 seriousme

Sry for the late response.

One of the key reasons to want to use OAS 3.1 over 3.0.x is the support for unevaluatedProperties addition, as the additionalProperties option that is supported in OAS 3.0.x is of limited use

I'm using TypeSpec to author and generate OAS, using extends and composition a fair bit to keep things DRY across all my endpoints. With just additionalProperties at my disposal in OAS 3.0.x, the end result (Swagger docs, validation) leaves much to be wished for I'm afraid.

Any downsides you can think of overriding AJV versions in Fastify like you proposed?

p-bakker avatar Apr 29 '25 07:04 p-bakker

The only downsides I can think of are:

  • schema 07 has better performance according to AJV docs
  • schema 2019/2020 is relatively new in AJV
  • you need some extra code to override AJV in fastify

Unless you run a high volume API I think you should be ok. You could post an issue in the Fastify repository and ask if they can make it more easy to use newer AJV schema versions.

Hope this helps!

Kind regards, Hans

seriousme avatar Apr 29 '25 17:04 seriousme

Thx, managed to get it going, haven't run benchmarks yet

p-bakker avatar May 01 '25 17:05 p-bakker