fix: detect property type changes on referenced component schemas in OpenAPI 3.1

IN
6h ago
+110-20

Fixes #910

Problem

In OpenAPI 3.1 documents, a type change on a property of a referenced component schema was silently ignored: getChangedOperations() and getChangedSchemas() came back empty. The identical change in an OpenAPI 3.0 document is detected as INCOMPATIBLE (covered by SchemaDiffTest#schemaPropertyTypeChanged with the schema-props-type-handling-1/2.yaml fixtures, as noted in the issue triage).

Root cause

swagger-parser deserializes OpenAPI 3.1 schemas into JsonSchema instances in which the type keyword is stored in the types set (Schema#getTypes()), while Schema#getType() returns null. The type-change gate in SchemaDiff#computeDiffForReal compared only getType(), so for 3.1 it compared null with null and never fired — the property type change was dropped (property diffs inside SchemaDiffResult never look at the type).

For OpenAPI 3.0, getType() carries the type, so the gate fired and produced the changedType result, which ChangedSchema classifies as INCOMPATIBLE (incompatible.schema.type.changed is enabled by default).

Fix

Compare the effective type set (union of getType() and getTypes()) in addition to the raw getType() string:

  • OpenAPI 3.1 (JsonSchema): type=null, types in getTypes() → union is the type carrier → type changes are now detected.
  • OpenAPI 3.0 typed schemas (StringSchema, ObjectSchema, ...): both type and types are populated → union is unchanged, no behavior change.
  • OpenAPI 3.0 composed schemas merged from their allOf/anyOf children (SchemaDiff#addSchema copies type but not types): only type is populated → union keeps these comparisons working exactly as before (allOf-equivalence tests AllOfDiffTest / Issue887Test confirm no regression).

Because the fix reuses the exact same getTypeChangedSchema path that OpenAPI 3.0 takes, the classification is identical to 3.0: the property reports changedType=true, the schema/operation is reported as changed and classified INCOMPATIBLE.

Tests

  • SchemaDiffTest#schemaPropertyTypeChanged31 mirrors the 3.0 type-change test using the issue's spec pair (GET /widgets, 200 response, `` to Widget, Widget.properties.weight.type integer → string, openapi: 3.1.0): fixtures schema-props-type-handling-3.1-1.yaml / -2.yaml. It failed before the fix (changedOperations expected 1 but was 0, matching the issue) and passes after.

Scope notes

  • format changes in 3.1 are already detected (the parser stores format in the regular field and the gate compares it) — verified; no other property attribute shares the types gap.
  • Multi-type keywords (type: [integer, string]) are compared as sets, so reordering does not produce a false change.

Summary by cubic

Fixes #910. Property type changes on referenced component schemas in OpenAPI 3.1 documents were silently ignored — getChangedOperations() and getChangedSchemas() returned empty. The type-change gate now compares the effective type set (union of getType() and getTypes(), which OpenAPI 3.1 deserialization populates), so these changes are detected and classified as INCOMPATIBLE, matching OpenAPI 3.0 behavior.

  • Dropped the raw getType() comparison so equivalent schemas with the same effective type no longer report a false change.
  • resolveComposedSchema now flattens allOf/anyOf on any schema (3.1 compositions deserialize into JsonSchema, not ComposedSchema) and addSchema propagates getTypes(), so composed schemas keep their effective types.
  • Added the schemaPropertyTypeChanged31 regression test with the issue's spec pair, asserting the INCOMPATIBLE classification.