Any OpenAPI validator that properly validates discriminator against data?
See original GitHub issueI would like to use an OpenAPI schema with a discriminator, then validate some input againts the schema. Thought this would be really easy-- there are so many validators out there that say they have discriminator support… and none of them I’ve tried so far worked! Seems like a fundamental task that anyone working with OpenAPI would need to perform, so maybe there’s obvious and easy solution and I’m just not seeing it or I’m doing something wrong (maybe the spec I am using is flawed?)
In particular, I would like to do the following:
- Given an OpenAPI spec that includes a POST request body using a schema with a discriminator, start a localhost web server on any port
- Send a POST request using curl to the above service, and receive an accept/reject response based on whether the POSTed data conformed to the request body schema
I have tried the following, and in each case, I got the same result: validation worked fine in general, but failed to throw an error when the mapped schema and the discriminator value did not match (see specific example below)
The specific test case I used is as follows:
- the spec describes a polymorphic object called Object, which has two subclasses: “obj1” and “obj2”, each with a corresponding “properties” object that contains “property1a” & “property1b” in the case of “obj1”, and “property2a” & “property2b” in the case of “obj2”
- the test cases are i) a valid object, and ii) an invalid object that contains type “obj2” but properties corresponding to the obj1 subclass properties schema
Test Case 1 (valid data):
{
"id": "hi",
"type": "obj1",
"properties": {
"property1a": 1,
"property1b": 2
}
}
curl command:
curl -X POST -k 'http://localhost:3000/v1/object/hi' -H 'Content-type: application/json' --data '{"id":"hi","type":"obj1","properties":{"property1a":1,"property1b":2}}'
Test Case 2 (invalid data, validator properly rejects):
{
"id": "hi",
"type": "obj1",
"properties": {
"nonexistent_property": 1,
"property1b": 2
}
}
Notice that nonexistent_property
is invalid. All of the validators I tried correctly reject this
curl -X POST -k 'http://localhost:3000/v1/object/hi' -H 'Content-type: application/json' --data '{"id":"hi","type":"obj2","properties":{"nonexistent_property":1,"property1b":2}}'
Test Case 3 (validator should throw an error, but does not!):
{
"id": "hi",
"type": "obj2",
"properties": {
"property1a": 1,
"property1b": 2
}
}
Notice that the type is obj2 but the properties are those corresponding to obj1. None of the validators reject this-- but they should, right?
curl command:
curl -X POST -k 'http://localhost:3000/v1/object/hi' -H 'Content-type: application/json' --data '{"id":"hi","type":"obj2","properties":{"property1a":1,"property1b":2}}'
YAML:
openapi: "3.0.0"
info:
version: "1.0.0"
title: "Discriminator example"
license:
name: "MIT"
servers:
- url: "http://localhost/v1"
components:
schemas:
Error:
type: "object"
required:
- "code"
- "message"
properties:
code:
type: "integer"
format: "int32"
message:
type: "string"
Object1Properties:
type: "object"
required:
- "property1a"
- "property1b"
properties:
property1a:
type: "string"
property1b:
type: "string"
Object2Properties:
type: "object"
required:
- "property2a"
- "property2b"
properties:
property2a:
type: "string"
property2b:
type: "string"
Object:
type: "object"
required:
- "id"
- "type"
- "properties"
properties:
id:
type: "string"
type:
type: "string"
enum:
- "obj1"
- "obj2"
properties:
oneOf:
-
$ref: "#/components/schemas/Object1Properties"
-
$ref: "#/components/schemas/Object2Properties"
discriminator:
propertyName: "type"
mapping:
obj1: "#/components/schemas/Object1Properties"
obj2: "#/components/schemas/Object2Properties"
requestBodies:
Object:
description: "Object schema in request body"
content:
application/json:
schema:
$ref: "#/components/schemas/Object"
parameters:
objectId:
name: "objectId"
in: "path"
required: true
description: "Id of the object"
schema:
type: "string"
responses:
defaultError:
description: "Unexpected error"
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
paths:
/object/{objectId}:
post:
summary: "Create an object"
operationId: "createObject"
parameters:
-
$ref: "#/components/parameters/objectId"
tags:
- "objects"
requestBody:
$ref: "#/components/requestBodies/Object"
responses:
201:
description: "Object created"
content:
application/json:
schema:
$ref: "#/components/schemas/Object"
default:
$ref: "#/components/responses/defaultError"
Example of validator server using express-openapi-validator is attached. validation_server.zip
Any help is much appreciated!
Issue Analytics
- State:
- Created 4 years ago
- Comments:15 (6 by maintainers)
Top GitHub Comments
I agree. That said, the fact that no validator enforcing the discriminator seems to exist makes me wonder whether any code generator would have relied on it. It just seems unlikely that anyone going through the trouble of generating code with that feature would not require, as a part of the process, a testing framework that required validation. Perhaps they didn’t care about that test coverage, or perhaps they built their own validator and kept it non-public or I just wasn’t able to find it-- am certainly not saying you shouldn’t first gauge the community opinion, and am certainly willing to place some bets on how that will turn out!
Either way, thank you for your responses, which have been far more helpful than the many hours I have spent trying to find / configure validators to enforce the discriminator.
Unless something has recently changed, that validator does not support discriminator. The comment in https://github.com/cdimascio/express-openapi-validator/issues/95#issuecomment-546545269 says “Yes”, but then it says “indirectly” and goes on to say it only supports when “removing discriminator in v3 should always result in the same validation outcome”. In other words, when it sees “discriminator”, it does not break, but it simply ignores it. From a practical standpoint, as far as I’m concerned, “ignoring” is definitely not the same as “supporting”-- i.e. it means “No”, it does not support.