From 59f07c3da104a8040045da7e1e74890197365a35 Mon Sep 17 00:00:00 2001 From: Aliaksandr Pinchuk Date: Mon, 23 Feb 2026 10:42:37 +0100 Subject: [PATCH] NullPointerException when oneOf changes to anyOf in response schema Fixes #381 --- .../ComposedSchemaDiffResult.java | 20 ++++++----- .../openapidiff/core/OneOfDiffTest.java | 7 ++++ core/src/test/resources/oneOf_to_anyOf_1.yaml | 34 +++++++++++++++++++ core/src/test/resources/oneOf_to_anyOf_2.yaml | 34 +++++++++++++++++++ 4 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 core/src/test/resources/oneOf_to_anyOf_1.yaml create mode 100644 core/src/test/resources/oneOf_to_anyOf_2.yaml diff --git a/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/ComposedSchemaDiffResult.java b/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/ComposedSchemaDiffResult.java index 2f86318eb..336c8b290 100644 --- a/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/ComposedSchemaDiffResult.java +++ b/core/src/main/java/org/openapitools/openapidiff/core/compare/schemadiffresult/ComposedSchemaDiffResult.java @@ -117,16 +117,18 @@ private Map getSchema( private Map getMapping(ComposedSchema composedSchema) { Map reverseMapping = new LinkedHashMap<>(); - for (Schema schema : composedSchema.getOneOf()) { - String ref = schema.get$ref(); - if (ref == null) { - continue; - } - String schemaName = refPointer.getRefName(ref); - if (schemaName == null) { - throw new IllegalArgumentException("invalid schema: " + ref); + if (composedSchema.getOneOf() != null) { + for (Schema schema : composedSchema.getOneOf()) { + String ref = schema.get$ref(); + if (ref == null) { + continue; + } + String schemaName = refPointer.getRefName(ref); + if (schemaName == null) { + throw new IllegalArgumentException("invalid schema: " + ref); + } + reverseMapping.put(ref, schemaName); } - reverseMapping.put(ref, schemaName); } if (composedSchema.getDiscriminator() != null diff --git a/core/src/test/java/org/openapitools/openapidiff/core/OneOfDiffTest.java b/core/src/test/java/org/openapitools/openapidiff/core/OneOfDiffTest.java index 87cabc709..bc7b316ee 100644 --- a/core/src/test/java/org/openapitools/openapidiff/core/OneOfDiffTest.java +++ b/core/src/test/java/org/openapitools/openapidiff/core/OneOfDiffTest.java @@ -18,6 +18,8 @@ public class OneOfDiffTest { private final String OPENAPI_DOC8 = "oneOf_discriminator-missing_1.yaml"; private final String OPENAPI_DOC9 = "oneOf_discriminator-missing_2.yaml"; private final String OPENAPI_DOC10 = "unnamed_oneof_schema_1.yaml"; + private final String OPENAPI_DOC11 = "oneOf_to_anyOf_1.yaml"; + private final String OPENAPI_DOC12 = "oneOf_to_anyOf_2.yaml"; @Test public void testDiffSame() { @@ -59,4 +61,9 @@ public void testOneOfDiscrimitatorMissingSameOrder() { public void testOneOfDiscrimitatorMissingDifferentOrder() { assertOpenApiAreEquals(OPENAPI_DOC8, OPENAPI_DOC9); } + + @Test // issue #381 + public void testOneOfToAnyOfDoesNotThrow() { + assertOpenApiChangedEndpoints(OPENAPI_DOC11, OPENAPI_DOC12); + } } diff --git a/core/src/test/resources/oneOf_to_anyOf_1.yaml b/core/src/test/resources/oneOf_to_anyOf_1.yaml new file mode 100644 index 000000000..1db19e0d0 --- /dev/null +++ b/core/src/test/resources/oneOf_to_anyOf_1.yaml @@ -0,0 +1,34 @@ +openapi: 3.0.1 +info: + title: oneOf to anyOf repro (old) + version: 1.0.0 +paths: + /example: + get: + responses: + "200": + description: ok + content: + application/json: + schema: + $ref: "#/components/schemas/Result" +components: + schemas: + Result: + oneOf: + - $ref: "#/components/schemas/TypeA" + - $ref: "#/components/schemas/TypeB" + TypeA: + type: object + required: + - a + properties: + a: + type: string + TypeB: + type: object + required: + - b + properties: + b: + type: string diff --git a/core/src/test/resources/oneOf_to_anyOf_2.yaml b/core/src/test/resources/oneOf_to_anyOf_2.yaml new file mode 100644 index 000000000..72ab53aa3 --- /dev/null +++ b/core/src/test/resources/oneOf_to_anyOf_2.yaml @@ -0,0 +1,34 @@ +openapi: 3.0.1 +info: + title: oneOf to anyOf repro (new) + version: 1.0.0 +paths: + /example: + get: + responses: + "200": + description: ok + content: + application/json: + schema: + $ref: "#/components/schemas/Result" +components: + schemas: + Result: + anyOf: + - $ref: "#/components/schemas/TypeA" + - $ref: "#/components/schemas/TypeB" + TypeA: + type: object + required: + - a + properties: + a: + type: string + TypeB: + type: object + required: + - b + properties: + b: + type: string