Incorrect validation of readOnly and required property
If the property is marked as
readOnly
beingtrue
and is in therequired
list, therequired
will take effect on the response only.
https://swagger.io/specification/
swagger-request-validator-core version 2.28.2 does not honor this though. Consider the following:
Validator configuration:
String openApiUrl = URI.create(...).toString();
ParseOptions parseOptions = new ParseOptions();
parseOptions.setResolve(true);
parseOptions.setResolveFully(false);
parseOptions.setResolveCombinators(true);
OpenApiInteractionValidator validator = OpenApiInteractionValidator
.createForSpecificationUrl(openApiUrl)
.withParseOptions(parseOptions)
.build();
OpenAPI:
---
openapi: 3.0.3
info:
title: readonly-not-validating
version: v1
paths:
/:
post:
summary: Create a new item.
operationId: postItem
requestBody:
description: Create new item.
content:
application/json:
schema:
$ref: '#/components/schemas/Item'
required: true
responses:
"201":
description: Item created.
components:
schemas:
Item:
required:
- id
- description
type: object
properties:
id:
description: An ID.
type: string
readOnly: true
description:
description: Some description.
type: string
Request body:
{
"description": "required description"
}
Then the following validation error will be provided:
{
"key" : "validation.request.body.schema.discriminator",
"level" : "ERROR",
"message" : "Failed validation of discriminator schema '/components/schemas/Item'",
"nestedMessages" : [ {
"key" : "validation.request.body.schema.required",
"level" : "ERROR",
"message" : "Object has missing required properties ([\"description\"])",
"context" : {
"pointers" : {
"instance" : "/",
"schema" : "/components/schemas/Item"
}
}
} ],
"context" : {
"requestPath" : "/",
"apiRequestContentType" : "application/json",
"location" : "REQUEST",
"pointers" : {
"instance" : "/",
"schema" : "/components/schemas/Item"
},
"requestMethod" : "POST"
}
}
when no validation error should be given.
Comments (2)
-
-
reporter Hi,
Sorry, the example I gave above actually works and gives no validation errors as expected. I got the error on a more complex example, but tried to simplify it, without testing it first. Again sorry for that.
Here is an example that actually does give an error:
Validator configuration:
String openApiUrl = URI.create(...).toString(); ParseOptions parseOptions = new ParseOptions(); parseOptions.setResolve(true); parseOptions.setResolveFully(false); parseOptions.setResolveCombinators(true); LevelResolver levelResolver = LevelResolver.create() .withLevel("validation.schema.additionalProperties", IGNORE) // Necessary as the properties in Item would otherwise give an error for properties not defined. But it makes no difference in the error message regarding readOnly required. .build(); OpenApiInteractionValidator validator = OpenApiInteractionValidator .createForSpecificationUrl(openApiUrl) .withParseOptions(parseOptions) .withLevelResolver(levelResolver) .build();
OpenAPI:
--- openapi: 3.0.3 info: title: readonly-not-validating version: v1 paths: /: post: summary: Create a new item. operationId: ref requestBody: description: Create new item. content: application/json: schema: $ref: '#/components/schemas/Item' required: true responses: "201": description: Item created. components: schemas: Ownership: required: - shares type: object properties: shares: description: List of shares minItems: 0 type: array items: $ref: '#/components/schemas/Share' readOnly: true Share: required: - share type: object properties: shareId: readOnly: true description: Share id. type: string nullable: true share: description: A decimal number indicating the size of this share where 1 is 100%. type: number example: 0.5 OwnershipItem: required: - mainOwner type: object allOf: - $ref: '#/components/schemas/Item' properties: mainOwner: type: string readOnly: true ownership: allOf: - $ref: '#/components/schemas/Ownership' - description: Identifies how the item is owned. readOnly: true Item: required: - type - description type: object properties: id: description: An ID. type: string readOnly: true description: description: Some description. type: string type: description: Descriminator enum: - OwnershipItem type: string discriminator: propertyName: type mapping: OwnershipItem: '#/components/schemas/OwnershipItem'
POST request body:
{ "type": "OwnershipItem", "description": "required description" }
Then the following validation error will be provided:
{ "messages" : [ { "key" : "validation.request.body.schema.discriminator", "level" : "ERROR", "message" : "Failed validation of discriminator schema '/components/schemas/OwnershipItem'", "nestedMessages" : [ { "key" : "validation.request.body.schema.required", "level" : "ERROR", "message" : "Object has missing required properties ([\"mainOwner\"])", "context" : { "pointers" : { "instance" : "/", "schema" : "/components/schemas/OwnershipItem" } } } ], "context" : { "requestPath" : "/ref", "apiRequestContentType" : "application/json", "location" : "REQUEST", "pointers" : { "instance" : "/", "schema" : "/components/schemas/OwnershipItem" }, "requestMethod" : "POST" } } ] }
- Log in to comment
Thanks for raising this. Can I just confirm that the error you are posting comes from the schema + example you’ve given?
The reason I ask - it is reporting an error on the
description
field (not theid
field that you’ve marked asreadOnly
). And it is reporting it as part ofdiscriminator
validation, which I would only expect if you were usingallOf
or similar with thediscriminator
keyword (which I can’t see in your examples).So, if these examples are accurate then it looks like the problem is not with the
readOnly
validation but something else instead.