Test allOf and oneOf guidelines with validator tooling
When testing one of the examples with oneOf of two object subschemas, I noticed that it's missing required properties to make the subschemas non-overlapping:
OneOfTwoObjects:
type: object
oneOf:
- type: object
properties:
propertyA:
type: string
# required: [propertyA] --> needs to be added, else no value is valid because any object matches both subschemas
- type: object
properties:
propertyB:
type: string
# required: [propertyB] --> needs to be added, else no value is valid because any object matches both subschemas
However, when generating code with the required added, both propertyA and propertyB getters get a @NotNull annotation in the generated class combining all properties.
update: done a test with a variant that uses shared property in subschemas, but with different constraints:
OneOfTwoObjects:
type: object
required: [sharedProperty]
oneOf:
- type: object
properties:
sharedProperty:
type: string
pattern: "$A.*$"
- type: object
properties:
sharedProperty:
type: string
pattern: "$B.*$"
Should work for swagger-request-validator, but for codegen with bean validation enabled, this results in only one of the two pattern constraints 'survives':
@NotNull @Pattern(regexp = "$B.*$")
@Schema(name = "sharedProperty", requiredMode = Schema.RequiredMode.REQUIRED)
@JsonProperty("sharedProperty")
public String getSharedProperty() {
return sharedProperty;
}
So, when oneOf subschemas:
- are overlapping -> incorrect, values are always invalid
- are disjoint by required property -> incorrect @NotNull
- are disjoint by constraints on property -> incorrect bean validation annotations
So lots of pitfalls ... maybe we should recommend to limit usage of oneOf to only required, e.g.
oneOf:
- required: [propertyA]
- required: [propertyB]
for the example "Making a property of another schema required", validation of the property being required doesn't seem to work (using swagger-request-validator 2.46.0, couldn't get it to work in v2.44.1 ) unless declaring it as required on root schema level. Then again, declaring it within the allOf, is useful to trigger code generation to create an inheritance relationship.
components:
schemas:
ObjectSchema:
type: object
properties:
firstProperty:
type: string
secondProperty:
type: string
RestrictedSchema:
type: object
required: [firstProperty] # this seems necessary to make validation work
allOf:
- $ref: "#/components/schemas/ObjectSchema"
- required: [firstProperty] # makes property defined in ObjectSchema required
type: object # object type already in ObjectSchema, but will generate inheritance in code generation
The other oneOf/allOf examples work as intended.
REST WG is OK that oneOf with object type subschemas shouldn't be used. We can add the swagger-request-validator buggy behavior in the example, but not in the rule bc it might be fixed in a next release. I'll create a PR.
PR created.
restricts allowed usage to:
- subschemas without a type constraint that only list required properties
- subschemas with an enum of a simple type (i.e. no array or object)
The enum case works, because of the SIMPLIFY_ONEOF_ANYOF_ENUM normalizer that's active by default.