From ef2cf163dfdf19af5a5a8dc1ab6651dcfcd43924 Mon Sep 17 00:00:00 2001 From: "sonatypeoss[bot]" <68616245+sonatypeoss[bot]@users.noreply.github.com> Date: Mon, 13 Oct 2025 15:20:03 +0200 Subject: [PATCH 1/4] bump snapshot 2.1.36-SNAPSHOT (#2240) Co-authored-by: daniel-kmiecik --- modules/swagger-parser-cli/pom.xml | 4 ++-- modules/swagger-parser-core/pom.xml | 2 +- modules/swagger-parser-safe-url-resolver/pom.xml | 2 +- modules/swagger-parser-v2-converter/pom.xml | 2 +- modules/swagger-parser-v3/pom.xml | 2 +- modules/swagger-parser/pom.xml | 2 +- pom.xml | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/swagger-parser-cli/pom.xml b/modules/swagger-parser-cli/pom.xml index fb5dfd9be2..09c8b5aa3f 100644 --- a/modules/swagger-parser-cli/pom.xml +++ b/modules/swagger-parser-cli/pom.xml @@ -5,7 +5,7 @@ swagger-parser-project io.swagger.parser.v3 - 2.1.35 + 2.1.36-SNAPSHOT ../.. 4.0.0 @@ -91,7 +91,7 @@ io.swagger.parser.v3 swagger-parser-v3 - 2.1.35 + 2.1.36-SNAPSHOT compile diff --git a/modules/swagger-parser-core/pom.xml b/modules/swagger-parser-core/pom.xml index 8f214c7d78..062f088038 100644 --- a/modules/swagger-parser-core/pom.xml +++ b/modules/swagger-parser-core/pom.xml @@ -3,7 +3,7 @@ io.swagger.parser.v3 swagger-parser-project - 2.1.35 + 2.1.36-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-parser-safe-url-resolver/pom.xml b/modules/swagger-parser-safe-url-resolver/pom.xml index c890436d6c..3b9629c0ec 100644 --- a/modules/swagger-parser-safe-url-resolver/pom.xml +++ b/modules/swagger-parser-safe-url-resolver/pom.xml @@ -6,7 +6,7 @@ io.swagger.parser.v3 swagger-parser-project - 2.1.35 + 2.1.36-SNAPSHOT ../../pom.xml diff --git a/modules/swagger-parser-v2-converter/pom.xml b/modules/swagger-parser-v2-converter/pom.xml index ab1a5bb3ef..848c399aae 100644 --- a/modules/swagger-parser-v2-converter/pom.xml +++ b/modules/swagger-parser-v2-converter/pom.xml @@ -3,7 +3,7 @@ io.swagger.parser.v3 swagger-parser-project - 2.1.35 + 2.1.36-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-parser-v3/pom.xml b/modules/swagger-parser-v3/pom.xml index ffce61e466..4788cef4ba 100644 --- a/modules/swagger-parser-v3/pom.xml +++ b/modules/swagger-parser-v3/pom.xml @@ -3,7 +3,7 @@ io.swagger.parser.v3 swagger-parser-project - 2.1.35 + 2.1.36-SNAPSHOT ../.. 4.0.0 diff --git a/modules/swagger-parser/pom.xml b/modules/swagger-parser/pom.xml index 25bbd8bdcc..8348eb39c8 100644 --- a/modules/swagger-parser/pom.xml +++ b/modules/swagger-parser/pom.xml @@ -3,7 +3,7 @@ io.swagger.parser.v3 swagger-parser-project - 2.1.35 + 2.1.36-SNAPSHOT ../.. 4.0.0 diff --git a/pom.xml b/pom.xml index 071c0f5a69..11572dacf9 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 io.swagger.parser.v3 swagger-parser-project - 2.1.35 + 2.1.36-SNAPSHOT pom swagger-parser-project swagger-parser-project From 676c821018b77793a5c49213cbf489bab8b62b49 Mon Sep 17 00:00:00 2001 From: IgorMaj Date: Thu, 20 Nov 2025 14:56:05 +0100 Subject: [PATCH 2/4] Fix discriminator key and value were getting mixed up resulting in DuplicateKeyError (#2222) --- .../processors/ExternalRefProcessor.java | 2 +- .../swagger/v3/parser/test/Issue2222Test.java | 33 ++++++++++ .../v3/parser/test/OpenAPIV3RefTest.java | 6 +- .../src/test/resources/issue-2222/mypath.yaml | 61 +++++++++++++++++++ .../test/resources/issue-2222/openapi.yaml | 9 +++ 5 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/Issue2222Test.java create mode 100644 modules/swagger-parser-v3/src/test/resources/issue-2222/mypath.yaml create mode 100644 modules/swagger-parser-v3/src/test/resources/issue-2222/openapi.yaml diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java index af3b6aedbc..0ad84145bf 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java @@ -250,7 +250,7 @@ private void processSchema(Schema property, String file) { ComposedSchema composed = (ComposedSchema) property; final Map refMap = Optional.ofNullable(composed.getDiscriminator()) .map(Discriminator::getMapping).orElse(Collections.emptyMap()).entrySet() - .stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); + .stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); Map refCache = (!refMap.isEmpty() && (composed.getAnyOf() != null || composed.getOneOf() != null)) ? Stream.of( composed.getAnyOf(), composed.getOneOf() diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/Issue2222Test.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/Issue2222Test.java new file mode 100644 index 0000000000..a6d2665a48 --- /dev/null +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/Issue2222Test.java @@ -0,0 +1,33 @@ +package io.swagger.v3.parser.test; + +import io.swagger.v3.core.util.Json; +import io.swagger.v3.oas.models.media.Discriminator; +import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.parser.OpenAPIV3Parser; +import io.swagger.v3.parser.core.models.ParseOptions; +import io.swagger.v3.parser.core.models.SwaggerParseResult; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class Issue2222Test { + + @Test + public void shouldMapSameEntitiesToDifferentDiscriminatorValues() { + ParseOptions options = new ParseOptions(); + options.setResolveFully(true); + SwaggerParseResult result = new OpenAPIV3Parser().readLocation("issue-2222/openapi.yaml", null, options); + + // No error/warning messages should be present, especially Duplicate key ones + assertEquals(0, result.getMessages().size()); + assertEquals(1, result.getOpenAPI().getPaths().size()); + ApiResponse response = result.getOpenAPI().getPaths().get("/mypath").readOperations().get(0).getResponses().get("200"); + Discriminator discriminator = response.getContent().get("application/json").getSchema().getItems().getDiscriminator(); + assertEquals("discriminatorProperty", discriminator.getPropertyName()); + assertEquals("#/components/schemas/TypeA", discriminator.getMapping().get("ONE")); + assertEquals("#/components/schemas/TypeB", discriminator.getMapping().get("TWO")); + assertEquals("#/components/schemas/TypeB", discriminator.getMapping().get("THREE")); + assertEquals("#/components/schemas/TypeB", discriminator.getMapping().get("FOUR")); + assertEquals("#/components/schemas/TypeB", discriminator.getMapping().get("FIVE")); + } +} diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3RefTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3RefTest.java index c8dac007b7..5cfaf6af16 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3RefTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3RefTest.java @@ -83,7 +83,11 @@ public void testDiscriminatorMappingRefsUpdated() { Set allOfs = ((List)reqSchema.getAnyOf()) .stream().map(Schema::get$ref).collect(Collectors.toSet()); assertTrue(allOfs.stream().allMatch(s -> s.contains(COMPONENTS_SCHEMAS_REF)),"Schema mappings are processed"); - assertTrue(allOfs.containsAll(discriminator),"Discriminator mappings are updated"); + Set allOfsNames = allOfs.stream() + .map(of -> of.split("/schemas/")[1]).collect(Collectors.toSet()); + Collection discriminatorNames = discriminator.stream().map(of -> of.split("/schemas/")[1] + .replace(".json","")).collect(Collectors.toSet()); + assertTrue(allOfsNames.containsAll(discriminatorNames),"Discriminator mappings are updated"); } diff --git a/modules/swagger-parser-v3/src/test/resources/issue-2222/mypath.yaml b/modules/swagger-parser-v3/src/test/resources/issue-2222/mypath.yaml new file mode 100644 index 0000000000..d77a77e18b --- /dev/null +++ b/modules/swagger-parser-v3/src/test/resources/issue-2222/mypath.yaml @@ -0,0 +1,61 @@ + get: + summary: Get all objects + operationId: getObjects + responses: + '200': + description: "List of all the objects." + content: + application/json: + schema: + type: array + items: + oneOf: + - $ref: '#/components/schemas/TypeA' + - $ref: '#/components/schemas/TypeB' + discriminator: + propertyName: discriminatorProperty + mapping: + ONE: '#/components/schemas/TypeA' + TWO: '#/components/schemas/TypeB' + THREE: '#/components/schemas/TypeB' + FOUR: '#/components/schemas/TypeB' + FIVE: '#/components/schemas/TypeB' + + components: + schemas: + BaseType: + type: object + required: + - discriminatorProperty + properties: + discriminatorProperty: + type: string + description: A property used to determine the concrete object type. + enum: [ONE, TWO, THREE, FOUR, FIVE] + id: + type: string + description: Unique identifier for the object. + + TypeA: + allOf: + - $ref: '#/components/schemas/BaseType' + - type: object + properties: + discriminatorProperty: + type: string + enum: [ONE] + name: + type: string + description: A name specific to TypeA. + + TypeB: + allOf: + - $ref: '#/components/schemas/BaseType' + - type: object + properties: + discriminatorProperty: + type: string + enum: [TWO, THREE, FOUR, FIVE] + value: + type: number + description: A numeric value specific to TypeB. \ No newline at end of file diff --git a/modules/swagger-parser-v3/src/test/resources/issue-2222/openapi.yaml b/modules/swagger-parser-v3/src/test/resources/issue-2222/openapi.yaml new file mode 100644 index 0000000000..a2ecba50c5 --- /dev/null +++ b/modules/swagger-parser-v3/src/test/resources/issue-2222/openapi.yaml @@ -0,0 +1,9 @@ +openapi: 3.0.0 +info: + title: Example API + version: 1.0.0 + description: Example API demonstrating polymorphic response with external schemas. + +paths: + /mypath: + $ref: './mypath.yaml' From bafaee7a566225300881f58c4c713836e9008ecd Mon Sep 17 00:00:00 2001 From: Daniel Kmiecik Date: Mon, 24 Nov 2025 12:19:15 +0100 Subject: [PATCH 3/4] fix: same name and different location in param + small refactor (#2250) Co-authored-by: Ewa Ostrowska --- .../processors/ExternalRefProcessor.java | 3 +- .../parser/processors/ParameterProcessor.java | 184 +++++++++--------- .../v3/parser/test/OpenAPIV3ParserTest.java | 130 +++++++------ .../ParserDeduplicationParameterTest.java | 133 +++++++++++++ .../test/resources/issue-2102/openapi30.json | 35 ++++ .../issue-2102/openapi30mixedRef.yaml | 18 ++ .../openapi30sameNameSameLocation.yaml | 18 ++ .../test/resources/issue-2102/openapi31.json | 35 ++++ 8 files changed, 399 insertions(+), 157 deletions(-) create mode 100644 modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/ParserDeduplicationParameterTest.java create mode 100644 modules/swagger-parser-v3/src/test/resources/issue-2102/openapi30.json create mode 100644 modules/swagger-parser-v3/src/test/resources/issue-2102/openapi30mixedRef.yaml create mode 100644 modules/swagger-parser-v3/src/test/resources/issue-2102/openapi30sameNameSameLocation.yaml create mode 100644 modules/swagger-parser-v3/src/test/resources/issue-2102/openapi31.json diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java index 0ad84145bf..4320f43208 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java @@ -96,8 +96,7 @@ public String processRefToExternalSchema(String $ref, RefFormat refFormat) { if(schema == null) { // stop! There's a problem. retain the original ref - LOGGER.warn("unable to load model reference from `" + $ref + "`. It may not be available " + - "or the reference isn't a valid model schema"); + LOGGER.warn("unable to load model reference from `{}`. It may not be available or the reference isn't a valid model schema", $ref); return $ref; } String newRef; diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ParameterProcessor.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ParameterProcessor.java index efdace6d93..6da973943c 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ParameterProcessor.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ParameterProcessor.java @@ -1,18 +1,17 @@ package io.swagger.v3.parser.processors; - +import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.examples.Example; -import io.swagger.v3.oas.models.media.Content; import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; -import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.parser.ResolverCache; import io.swagger.v3.parser.models.RefFormat; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import static io.swagger.v3.parser.util.RefUtils.computeRefFormat; import static io.swagger.v3.parser.util.RefUtils.isAnExternalRefFormat; @@ -33,137 +32,140 @@ public ParameterProcessor(ResolverCache cache, OpenAPI openAPI) { public ParameterProcessor(ResolverCache cache, OpenAPI openAPI, boolean openapi31) { this.cache = cache; this.openAPI = openAPI; - this.schemaProcessor = new SchemaProcessor(cache,openAPI, openapi31); - this.exampleProcessor = new ExampleProcessor(cache,openAPI); + this.schemaProcessor = new SchemaProcessor(cache, openAPI, openapi31); + this.exampleProcessor = new ExampleProcessor(cache, openAPI); this.externalRefProcessor = new ExternalRefProcessor(cache, openAPI); } public void processParameter(Parameter parameter) { - String $ref = parameter.get$ref(); - if($ref != null){ + processRefToExternalParameter(parameter, parameter.get$ref()); + if (parameter.getSchema() != null) { + schemaProcessor.processSchema(parameter.getSchema()); + } + processParameterExamples(parameter); + processParameterMediaTypeSchema(parameter); + } + + private void processRefToExternalParameter(Parameter parameter, String referencePath) { + if (referencePath != null) { RefFormat refFormat = computeRefFormat(parameter.get$ref()); - if (isAnExternalRefFormat(refFormat)){ - String newRef = externalRefProcessor.processRefToExternalParameter($ref, refFormat); + if (isAnExternalRefFormat(refFormat)) { + String newRef = externalRefProcessor.processRefToExternalParameter(referencePath, refFormat); if (newRef != null) { newRef = "#/components/parameters/" + newRef; parameter.set$ref(newRef); } } } - if (parameter.getSchema() != null){ - schemaProcessor.processSchema(parameter.getSchema()); - } - if (parameter.getExamples() != null){ - Map examples = parameter.getExamples(); - for(String exampleName: examples.keySet()){ - final Example example = examples.get(exampleName); - exampleProcessor.processExample(example); - } + } + + private void processParameterExamples(Parameter parameter) { + Map examples = parameter.getExamples(); + if (examples != null) { + examples.values().forEach(exampleProcessor::processExample); } - Schema schema = null; - if(parameter.getContent() != null) { - Map content = parameter.getContent(); - for( String mediaName : content.keySet()) { + } + + private void processParameterMediaTypeSchema(Parameter parameter) { + if (parameter.getContent() != null) { + Map content = parameter.getContent(); + for (String mediaName : content.keySet()) { MediaType mediaType = content.get(mediaName); - if(mediaType.getSchema()!= null) { - schema = mediaType.getSchema(); - if (schema != null) { - schemaProcessor.processSchema(schema); - } + if (mediaType.getSchema() != null) { + Optional schema = Optional.ofNullable(mediaType.getSchema()); + schema.ifPresent(schemaProcessor::processSchema); } } } } - public List processParameters(List parameters) { + public List processParameters(List parameters) { if (parameters == null) { return null; } - final List processedPathLevelParameters = new ArrayList<>(); final List refParameters = new ArrayList<>(); + final List processedPathLevelParameters = processPathLevelParams(parameters, refParameters); + + for (Parameter resolvedParameter : refParameters) { + int pos = 0; + for (Parameter param : processedPathLevelParameters) { + if (param.getName().equals(resolvedParameter.getName())) { + // ref param wins + processedPathLevelParameters.set(pos, resolvedParameter); + break; + } + pos++; + } + + } + processedPathLevelParameters.forEach(parameter -> { + if (parameter.getSchema() != null) { + schemaProcessor.processSchema(parameter.getSchema()); + } else if (parameter.getContent() != null) { + Map content = parameter.getContent(); + content.values().forEach(mediaType -> { + if (mediaType.getSchema() != null) { + schemaProcessor.processSchema(mediaType.getSchema()); + } + if (mediaType.getExamples() != null) { + mediaType.getExamples().values().forEach(exampleProcessor::processExample); + } + }); + + } + }); + + return processedPathLevelParameters; + } + + private List processPathLevelParams(List parameters, List refParameters) { + final List processedPathLevelParameters = new ArrayList<>(); for (Parameter parameter : parameters) { if (parameter.get$ref() != null) { RefFormat refFormat = computeRefFormat(parameter.get$ref()); final Parameter resolvedParameter = cache.loadRef(parameter.get$ref(), refFormat, Parameter.class); - if (parameter.get$ref().startsWith("#") && parameter.get$ref().indexOf("#/components/parameters") <= -1) { + if (parameter.get$ref().startsWith("#") && !parameter.get$ref().contains("#/components/parameters")) { //TODO: Not possible to add warning during resolve doesn't accept result as an input. Hence commented below line. //result.warning(location, "The parameter should use Reference Object to link to parameters that are defined at the OpenAPI Object's components/parameters."); continue; } - if(resolvedParameter == null) { + if (resolvedParameter == null) { // can't resolve it! processedPathLevelParameters.add(parameter); continue; } - // if the parameter exists, replace it - boolean matched = false; - for(Parameter param : processedPathLevelParameters) { - if(param != null && param.getName() != null && param.getName().equals(resolvedParameter.getName())) { - // ref param wins - matched = true; - break; - } - } - for(Parameter param : parameters) { - if(param.getName() != null) { - if (param.getName().equals(resolvedParameter.getName())) { - // ref param wins - matched = true; - break; - } - } - } + boolean matched = isParameterExist(parameters, processedPathLevelParameters, resolvedParameter); - if(matched) { + if (matched) { refParameters.add(resolvedParameter); - } - else { + } else { processedPathLevelParameters.add(resolvedParameter); } - } - else { + } else { processedPathLevelParameters.add(parameter); } } + return processedPathLevelParameters; + } - for(Parameter resolvedParameter : refParameters) { - int pos = 0; - for(Parameter param : processedPathLevelParameters) { - if(param.getName().equals(resolvedParameter.getName())) { - // ref param wins - processedPathLevelParameters.set(pos, resolvedParameter); - break; - } - pos++; - } - - } - - for (Parameter parameter : processedPathLevelParameters) { - Schema schema = parameter.getSchema(); - if(schema != null){ - schemaProcessor.processSchema(schema); - }else if(parameter.getContent() != null){ - Map content = parameter.getContent(); - for( String mediaName : content.keySet()) { - MediaType mediaType = content.get(mediaName); - if(mediaType.getSchema()!= null) { - schema = mediaType.getSchema(); - if (schema != null) { - schemaProcessor.processSchema(schema); - } - } - if(mediaType.getExamples() != null) { - for(Example ex: mediaType.getExamples().values()){ - exampleProcessor.processExample(ex); - } - } - } - - } + private static boolean isParameterExist(List parameters, List processedPathLevelParameters, Parameter resolvedParameter) { + // verify if the parameter exists, if yes, then replace it when name and location are the same + boolean matched = processedPathLevelParameters.stream() + .anyMatch(param -> param != null + && param.getName() != null + && param.getIn() != null + && param.getName().equals(resolvedParameter.getName()) + && param.getIn().equals(resolvedParameter.getIn())); + + if (!matched) { + matched = parameters.stream() + .anyMatch(param -> param != null + && param.getName() != null + && param.getIn() != null + && param.getName().equals(resolvedParameter.getName()) + && param.getIn().equals(resolvedParameter.getIn())); } - - return processedPathLevelParameters; + return matched; } } diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java index cba66fb1b1..42cab31d92 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java @@ -29,8 +29,10 @@ import java.io.FileInputStream; import java.io.IOException; import java.math.BigDecimal; +import java.net.MalformedURLException; import java.net.URL; import java.util.*; +import java.util.stream.Collectors; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; @@ -112,7 +114,7 @@ public void testIssue1621() { } @Test - public void testIssue1865() throws Exception { + public void testIssue1865() { ParseOptions options = new ParseOptions(); options.setResolve(true); SwaggerParseResult result = new OpenAPIV3Parser().readLocation("src/test/resources/issue-1865/openapi30.yaml", null, options); @@ -174,7 +176,7 @@ public void testIssue1780() { } @Test - public void testParametersAndResponsesAsNumbers() throws Exception { + public void testParametersAndResponsesAsNumbers() { ParseOptions options = new ParseOptions(); options.setResolve(true); options.setResolveResponses(true); @@ -187,7 +189,7 @@ public void testParametersAndResponsesAsNumbers() throws Exception { } @Test - public void testIssue1758() throws Exception{ + public void testIssue1758() { ParseOptions options = new ParseOptions(); SwaggerParseResult result = new OpenAPIV3Parser().readLocation("src/test/resources/issue1758.yaml", null, options); @@ -310,7 +312,7 @@ public void testIssue1637_StyleAndContent() throws IOException { } @Test - public void testIssue1643_True() throws Exception{ + public void testIssue1643_True() { ParseOptions options = new ParseOptions(); String issue1643 = "openapi: \"3.0.0\"\n" + "info:\n" + @@ -353,7 +355,7 @@ public void testIssue1643_True() throws Exception{ } @Test - public void testIssue1643_False() throws Exception{ + public void testIssue1643_False() { ParseOptions options = new ParseOptions(); options.setValidateInternalRefs(false); String issue1643 = "openapi: \"3.0.0\"\n" + @@ -397,7 +399,7 @@ public void testIssue1643_False() throws Exception{ } @Test - public void testExampleFormatByte() throws Exception{ + public void testExampleFormatByte() { ParseOptions options = new ParseOptions(); SwaggerParseResult result = new OpenAPIV3Parser().readLocation("src/test/resources/issue1630.yaml", null, options); @@ -423,7 +425,7 @@ public void testExampleFormatByte() throws Exception{ } @Test - public void testIssue1658() throws Exception{ + public void testIssue1658() { ParseOptions options = new ParseOptions(); options.setResolve(true); SwaggerParseResult result = new OpenAPIV3Parser().readLocation("src/test/resources/issue-1658/issue1658.yaml", null, options); @@ -440,7 +442,7 @@ public void testIssue1658() throws Exception{ } @Test - public void testIssue1644_NullValue() throws Exception{ + public void testIssue1644_NullValue() { ParseOptions options = new ParseOptions(); String issue1644 = "openapi: 3.0.0\n" + "info:\n" + @@ -466,7 +468,7 @@ public void testIssue1644_NullValue() throws Exception{ } @Test - public void testIssue1644_EmptyValue() throws Exception{ + public void testIssue1644_EmptyValue() { ParseOptions options = new ParseOptions(); String issue1644 = "openapi: 3.0.0\n" + "info:\n" + @@ -493,7 +495,7 @@ public void testIssue1644_EmptyValue() throws Exception{ @Test - public void testEmptyStrings_False() throws Exception{ + public void testEmptyStrings_False() { ParseOptions options = new ParseOptions(); options.setAllowEmptyString(false); SwaggerParseResult result = new OpenAPIV3Parser().readLocation("src/test/resources/empty-strings.yaml", null, options); @@ -510,7 +512,7 @@ public void testEmptyStrings_False() throws Exception{ @Test - public void testEmptyStrings_True() throws Exception{ + public void testEmptyStrings_True() { ParseOptions options = new ParseOptions(); options.setAllowEmptyString(true); SwaggerParseResult result = new OpenAPIV3Parser().readLocation("src/test/resources/empty-strings.yaml", null, options); @@ -994,7 +996,7 @@ public void testIssue1169noSplit() { @Test - public void testIssue339() throws Exception { + public void testIssue339() { OpenAPIV3Parser openAPIV3Parser = new OpenAPIV3Parser(); OpenAPI api = openAPIV3Parser.read("issue-339.yaml"); assertNotNull(api); @@ -1023,7 +1025,7 @@ public void testIssue1108() { } @Test - public void testRemoteParameterIssue1094() throws Exception{ + public void testRemoteParameterIssue1094() { OpenAPI result = new OpenAPIV3Parser().read("issue-1094/swagger.yaml"); Assert.assertNotNull(result); Assert.assertNotNull(result.getComponents().getSchemas().get("PlmnId")); @@ -1271,7 +1273,7 @@ public void testIssue719() { } @Test - public void issue682() throws Exception { + public void issue682() { OpenAPIV3Parser parser = new OpenAPIV3Parser(); ParseOptions options = new ParseOptions(); options.setResolve(true); @@ -1283,7 +1285,7 @@ public void issue682() throws Exception { } @Test - public void issue941() throws Exception { + public void issue941() { OpenAPIV3Parser parser = new OpenAPIV3Parser(); final OpenAPI result = parser.read("src/test/resources/sample/SwaggerPetstore.yaml"); @@ -1292,7 +1294,7 @@ public void issue941() throws Exception { } @Test - public void issueRelativeRefs2() throws Exception { + public void issueRelativeRefs2() { OpenAPIV3Parser parser = new OpenAPIV3Parser(); ParseOptions options = new ParseOptions(); options.setResolve(true); @@ -1313,7 +1315,7 @@ public void testPattern() { } @Test - public void testResolveEmpty() throws Exception{ + public void testResolveEmpty() throws IOException{ String pathFile = FileUtils.readFileToString(new File("src/test/resources/empty-oas.yaml")); ParseOptions options = new ParseOptions(); options.setResolveFully(true); @@ -1328,7 +1330,7 @@ public void testResolveEmpty() throws Exception{ @Test - public void testRemotePathItemIssue1103() throws Exception{ + public void testRemotePathItemIssue1103() { OpenAPI result = new OpenAPIV3Parser().read("issue-1103/remote-pathItem-swagger.yaml"); Assert.assertNotNull(result); Assert.assertNotNull(result.getPaths().get("/Translation/{lang}")); @@ -1336,21 +1338,21 @@ public void testRemotePathItemIssue1103() throws Exception{ } @Test - public void testRemoteParameterIssue1103() throws Exception{ + public void testRemoteParameterIssue1103() { OpenAPI result = new OpenAPIV3Parser().read("issue-1103/remote-parameter-swagger.yaml"); Assert.assertNotNull(result); Assert.assertEquals(result.getPaths().get("/Translation/{lang}").getPut().getParameters().get(0).getName(), "lang"); } @Test - public void testIssue1105() throws Exception { + public void testIssue1105() { OpenAPI openAPI = new OpenAPIV3Parser().read("issue-1105/swagger-api.yaml"); Assert.assertNotNull(openAPI); Assert.assertNotNull(openAPI.getComponents().getSchemas().get("ErrorCodeDescription")); } @Test - public void testRefAdditionalProperties() throws Exception { + public void testRefAdditionalProperties() { OpenAPI openAPI = new OpenAPIV3Parser().read("src/test/resources/relative/additionalProperties.yaml"); Assert.assertNotNull(openAPI); @@ -1361,7 +1363,7 @@ public void testRefAdditionalProperties() throws Exception { } @Test - public void testRefAndInlineAllOf() throws Exception { + public void testRefAndInlineAllOf() { ParseOptions options = new ParseOptions(); options.setResolve(true); options.setResolveFully(true); @@ -1375,7 +1377,7 @@ public void testRefAndInlineAllOf() throws Exception { } @Test - public void testComposedRefResolvingIssue628() throws Exception { + public void testComposedRefResolvingIssue628() { ParseOptions options = new ParseOptions(); options.setResolve(true); OpenAPI openAPI = new OpenAPIV3Parser().read("src/test/resources/composedSchemaRef.yaml", auths, options); @@ -1391,7 +1393,7 @@ public void testComposedRefResolvingIssue628() throws Exception { } @Test - public void testComposedSchemaAdjacent() throws Exception { + public void testComposedSchemaAdjacent() { ParseOptions options = new ParseOptions(); options.setResolve(true); OpenAPI openAPI = new OpenAPIV3Parser().read("src/test/resources/composedSchemaRef.yaml", auths, options); @@ -1406,7 +1408,7 @@ public void testComposedSchemaAdjacent() throws Exception { } @Test - public void testOneOfExternalRefConflictName() throws Exception { + public void testOneOfExternalRefConflictName() { OpenAPI openAPI = new OpenAPIV3Parser().read("./oneof_name_conflict/oneOf-external-ref-name-conflict.yaml"); Assert.assertNotNull(openAPI); Schema pet = openAPI.getComponents().getSchemas().get("Pet"); @@ -1416,14 +1418,14 @@ public void testOneOfExternalRefConflictName() throws Exception { } @Test - public void int64ExampleWithoutOverflow() throws Exception { + public void int64ExampleWithoutOverflow() { OpenAPI openAPI = new OpenAPIV3Parser().read("src/test/resources/int64example.yaml"); IntegerSchema date = ((IntegerSchema) openAPI.getPaths().get("/foo").getGet().getResponses().get("200").getContent().get("application/json").getSchema().getProperties().get("date")); Assert.assertEquals("1516042231144", date.getExample().toString()); } @Test - public void testRefPaths() throws Exception { + public void testRefPaths() { String yaml = "openapi: '3.0.0'\n" + "info:\n" + " version: 0.0.0\n" + @@ -1443,7 +1445,7 @@ public void testRefPaths() throws Exception { } @Test - public void testModelParameters() throws Exception { + public void testModelParameters() { String yaml = "openapi: '2.0'\n" + "info:\n" + " version: \"0.0.0\"\n" + @@ -1469,7 +1471,7 @@ public void testModelParameters() throws Exception { } @Test - public void testParseSharedPathParameters() throws Exception { + public void testParseSharedPathParameters() { String yaml = "openapi: '3.0.0'\n" + "info:\n" + @@ -1507,7 +1509,7 @@ public void testParseSharedPathParameters() throws Exception { } @Test - public void testParseRefPathParameters() throws Exception { + public void testParseRefPathParameters() { String yaml = "openAPI: '2.0'\n" + "info:\n" + @@ -1549,7 +1551,7 @@ public void testParseRefPathParameters() throws Exception { } @Test - public void testUniqueParameters() throws Exception { + public void testUniqueParameters() { String yaml = "openapi: 3.0.0\n" + "servers: []\n" + @@ -1609,12 +1611,12 @@ public void testUniqueParameters() throws Exception { } @Test - public void testLoadRelativeFileTree_Json() throws Exception { + public void testLoadRelativeFileTree_Json() { final OpenAPI openAPI = doRelativeFileTest("src/test/resources/relative-file-references/json/parent.json"); } @Test - public void testLoadExternalNestedDefinitions() throws Exception { + public void testLoadExternalNestedDefinitions() { OpenAPIV3Parser parser = new OpenAPIV3Parser(); final OpenAPI openAPI = parser.read("src/test/resources/nested-references/b.yaml"); @@ -1627,7 +1629,7 @@ public void testLoadExternalNestedDefinitions() throws Exception { } @Test - public void testLoadExternalNestedDefinitionsWithReferenceWithinSubfolder() throws Exception { + public void testLoadExternalNestedDefinitionsWithReferenceWithinSubfolder() { OpenAPIV3Parser parser = new OpenAPIV3Parser(); final OpenAPI openAPI = parser.read("src/test/resources/nested-references-2/main.yaml"); @@ -1648,7 +1650,7 @@ public void testLoadExternalNestedDefinitionsWithReferenceWithinSubfolder() thro } @Test - public void testLoadExternalNestedDefinitionsWithReferenceWithinSameFolder() throws Exception { + public void testLoadExternalNestedDefinitionsWithReferenceWithinSameFolder() { OpenAPIV3Parser parser = new OpenAPIV3Parser(); final OpenAPI openAPI = parser.read("src/test/resources/nested-references-3/main.yaml"); @@ -1669,7 +1671,7 @@ public void testLoadExternalNestedDefinitionsWithReferenceWithinSameFolder() thr } @Test - public void testLoadExternalNestedDefinitionsWithReferenceOnDifferentFolderLevels() throws Exception { + public void testLoadExternalNestedDefinitionsWithReferenceOnDifferentFolderLevels() { OpenAPIV3Parser parser = new OpenAPIV3Parser(); final OpenAPI openAPI = parser.read("src/test/resources/nested-references-4/main.yaml"); @@ -1690,7 +1692,7 @@ public void testLoadExternalNestedDefinitionsWithReferenceOnDifferentFolderLevel } @Test - public void testPetstore() throws Exception { + public void testPetstore() { OpenAPIV3Parser parser = new OpenAPIV3Parser(); ParseOptions options = new ParseOptions(); options.setResolve(true); @@ -1728,7 +1730,7 @@ public void testPetstore() throws Exception { } @Test - public void testFileReferenceWithVendorExt() throws Exception { + public void testFileReferenceWithVendorExt() { OpenAPIV3Parser parser = new OpenAPIV3Parser(); final OpenAPI openAPI = parser.read("src/test/resources/file-reference-with-vendor-ext/b.yaml"); Map definitions = openAPI.getComponents().getSchemas(); @@ -1739,13 +1741,13 @@ public void testFileReferenceWithVendorExt() throws Exception { } @Test - public void testTroublesomeFile() throws Exception { + public void testTroublesomeFile() { OpenAPIV3Parser parser = new OpenAPIV3Parser(); final OpenAPI openAPI = parser.read("src/test/resources/troublesome.yaml"); } @Test - public void testLoadRelativeFileTree_Yaml() throws Exception { + public void testLoadRelativeFileTree_Yaml() throws IOException { JsonToYamlFileDuplicator.duplicateFilesInYamlFormat("src/test/resources/relative-file-references/json", "src/test/resources/relative-file-references/yaml"); final OpenAPI openAPI = doRelativeFileTest("src/test/resources/relative-file-references/yaml/parent.yaml"); @@ -1754,7 +1756,7 @@ public void testLoadRelativeFileTree_Yaml() throws Exception { } @Test - public void testLoadRecursiveExternalDef() throws Exception { + public void testLoadRecursiveExternalDef() { OpenAPIV3Parser parser = new OpenAPIV3Parser(); final OpenAPI openAPI = parser.read("src/test/resources/file-reference-to-recursive-defs/b.yaml"); @@ -2090,7 +2092,7 @@ public void testCodegenPetstore() { } @Test - public void testCodegenIssue4555() throws Exception { + public void testCodegenIssue4555() { OpenAPIV3Parser parser = new OpenAPIV3Parser(); String yaml = "openapi: 3.0.0\n" + "info:\n" + @@ -2126,7 +2128,7 @@ public void testCodegenIssue4555() throws Exception { } @Test - public void testConverterIssue17() throws Exception { + public void testConverterIssue17() { String yaml = "openapi: 3.0.0\n" + "info:\n" + " version: 0.0.0\n" + @@ -2449,7 +2451,7 @@ public void checkAllOfWithRelativeReferencesIssue604() { } @Test(description = "A string example should not be over quoted when parsing a yaml string") - public void readingSpecStringShouldNotOverQuotingStringExample() throws Exception { + public void readingSpecStringShouldNotOverQuotingStringExample() { OpenAPIV3Parser parser = new OpenAPIV3Parser(); ParseOptions options = new ParseOptions(); options.setResolve(false); @@ -2460,7 +2462,7 @@ public void readingSpecStringShouldNotOverQuotingStringExample() throws Exceptio } @Test(description = "A string example should not be over quoted when parsing a yaml node") - public void readingSpecNodeShouldNotOverQuotingStringExample() throws Exception { + public void readingSpecNodeShouldNotOverQuotingStringExample() throws IOException { String yaml = Files.readFile(new FileInputStream("src/test/resources/over-quoted-example.yaml")); JsonNode rootNode = Yaml.mapper().readValue(yaml, JsonNode.class); OpenAPIV3Parser parser = new OpenAPIV3Parser(); @@ -2949,7 +2951,7 @@ public void testDuplicateHttpStatusCodesYaml() { @Test - public void testDiscriminatorSingleFileNoMapping() throws Exception { + public void testDiscriminatorSingleFileNoMapping() { OpenAPI openAPI = new OpenAPIV3Parser().read("./discriminator-mapping-resolution/single-file-no-mapping.yaml"); Assert.assertNotNull(openAPI); Schema cat = openAPI.getComponents().getSchemas().get("Cat"); @@ -2957,7 +2959,7 @@ public void testDiscriminatorSingleFileNoMapping() throws Exception { } @Test - public void testDiscriminatorSeparateFileNoMapping() throws Exception { + public void testDiscriminatorSeparateFileNoMapping() { OpenAPI openAPI = new OpenAPIV3Parser().read("./discriminator-mapping-resolution/main-no-mapping.yaml"); Assert.assertNotNull(openAPI); Schema cat = openAPI.getComponents().getSchemas().get("Cat"); @@ -2965,7 +2967,7 @@ public void testDiscriminatorSeparateFileNoMapping() throws Exception { } @Test - public void testDiscriminatorSingleFilePlainMapping() throws Exception { + public void testDiscriminatorSingleFilePlainMapping() { OpenAPI openAPI = new OpenAPIV3Parser().read("./discriminator-mapping-resolution/single-file-plain-mapping.yaml"); Assert.assertNotNull(openAPI); Schema cat = openAPI.getComponents().getSchemas().get("Cat"); @@ -2973,7 +2975,7 @@ public void testDiscriminatorSingleFilePlainMapping() throws Exception { } @Test - public void testDiscriminatorSeparateFilePlainMapping() throws Exception { + public void testDiscriminatorSeparateFilePlainMapping() { OpenAPI openAPI = new OpenAPIV3Parser().read("./discriminator-mapping-resolution/main-plain-mapping.yaml"); Assert.assertNotNull(openAPI); Schema cat = openAPI.getComponents().getSchemas().get("Cat"); @@ -2981,7 +2983,7 @@ public void testDiscriminatorSeparateFilePlainMapping() throws Exception { } @Test - public void testDiscriminatorSingleFileInternalMapping() throws Exception { + public void testDiscriminatorSingleFileInternalMapping() { OpenAPI openAPI = new OpenAPIV3Parser().read("./discriminator-mapping-resolution/single-file-internal-mapping.yaml"); Assert.assertNotNull(openAPI); Schema cat = openAPI.getComponents().getSchemas().get("Cat"); @@ -2989,7 +2991,7 @@ public void testDiscriminatorSingleFileInternalMapping() throws Exception { } @Test - public void testDiscriminatorSeparateFileInternalMapping() throws Exception { + public void testDiscriminatorSeparateFileInternalMapping() { OpenAPI openAPI = new OpenAPIV3Parser().read("./discriminator-mapping-resolution/main-internal-mapping.yaml"); Assert.assertNotNull(openAPI); Schema cat = openAPI.getComponents().getSchemas().get("Cat"); @@ -2997,7 +2999,7 @@ public void testDiscriminatorSeparateFileInternalMapping() throws Exception { } @Test - public void testDiscriminatorSameFileExternalMapping() throws Exception { + public void testDiscriminatorSameFileExternalMapping() { OpenAPI openAPI = new OpenAPIV3Parser().read("./discriminator-mapping-resolution/main-external-mapping.yaml"); Assert.assertNotNull(openAPI); Schema cat = openAPI.getComponents().getSchemas().get("Cat"); @@ -3005,7 +3007,7 @@ public void testDiscriminatorSameFileExternalMapping() throws Exception { } @Test - public void testDiscriminatorSeparateFileExternalMapping() throws Exception { + public void testDiscriminatorSeparateFileExternalMapping() { OpenAPI openAPI = new OpenAPIV3Parser().read("./discriminator-mapping-resolution/main-external-mapping-3files.yaml"); Assert.assertNotNull(openAPI); Schema cat = openAPI.getComponents().getSchemas().get("Cat"); @@ -3020,7 +3022,7 @@ public void testRelativePathIssue1543() { ParseOptions options = new ParseOptions(); options.setResolveFully(true); options.setResolve(true); - SwaggerParseResult readResult = parser.readLocation("src/test/resources/issue-1543/openapi.yaml", null, options); + SwaggerParseResult readResult = parser.readLocation("src/test/resources/issue-1543/openapi30.json", null, options); if (readResult.getMessages().size() > 0) { Assert.assertFalse(readResult.getMessages().get(0).contains("end -1")); @@ -3028,7 +3030,7 @@ public void testRelativePathIssue1543() { } @Test - public void testIssue1540() throws Exception{ + public void testIssue1540() { OpenAPI openAPI = new OpenAPIV3Parser().read("./issue-1540/a.json"); Assert.assertNotNull(openAPI); Map extensions = openAPI.getExtensions(); @@ -3043,7 +3045,7 @@ public void testIssue1540() throws Exception{ } @Test - public void testIssue1592() throws Exception { + public void testIssue1592() throws MalformedURLException { File file = new File("src/test/resources/issue-1592.jar"); URL url = new URL("jar:" + file.toURI() + "!/test.yaml"); ParseOptions options = new ParseOptions(); @@ -3054,7 +3056,7 @@ public void testIssue1592() throws Exception { } @Test - public void testIssue1266() throws Exception{ + public void testIssue1266() throws IOException{ String yamlString = FileUtils.readFileToString(new File("src/test/resources/issue-1266/issue-1266.yaml"), "UTF-8"); String yamlStringResolved = FileUtils.readFileToString(new File("src/test/resources/issue-1266/issue-1266-resolved.yaml"), "UTF-8"); ParseOptions options = new ParseOptions(); @@ -3116,8 +3118,8 @@ public void testIssue1891() { Schema typesModel = openAPI.getComponents().getSchemas().get("TypesModel"); Schema sharedModel = openAPI.getComponents().getSchemas().get("SharedModel"); - assertEquals("#/components/schemas/TypesModel", localModel.getProperties().get("sharedModelField").get$ref()); - assertEquals("#/components/schemas/SharedModel", typesModel.get$ref()); + assertEquals(localModel.getProperties().get("sharedModelField").get$ref(), "#/components/schemas/TypesModel"); + assertEquals(typesModel.get$ref(), "#/components/schemas/SharedModel"); assertNotNull(sharedModel); } @@ -3147,7 +3149,7 @@ public void testValidateExternalRefsFalse() { } @Test - public void testNullExample() throws Exception{ + public void testNullExample() throws IOException { String yamlString = FileUtils.readFileToString(new File("src/test/resources/null-full-example.yaml"), "UTF-8"); String yamlStringResolved = FileUtils.readFileToString(new File("src/test/resources/null-full-example-resolved.yaml"), "UTF-8"); ParseOptions options = new ParseOptions(); @@ -3159,7 +3161,7 @@ public void testNullExample() throws Exception{ } @Test - public void testInternalRefsValidation() throws Exception { + public void testInternalRefsValidation() throws IOException { String yamlString = FileUtils.readFileToString(new File("src/test/resources/internal-refs.yaml"), "UTF-8"); ParseOptions options = new ParseOptions(); SwaggerParseResult parseResult = new OpenAPIV3Parser().readContents(yamlString, null, options); @@ -3214,7 +3216,7 @@ public void test31SafeURLResolvingWithBlockedURL() { parseOptions.setResolveFully(true); parseOptions.setSafelyResolveURL(true); List allowList = Collections.emptyList(); - List blockList = Arrays.asList("petstore3.swagger.io"); + List blockList = Collections.singletonList("petstore3.swagger.io"); parseOptions.setRemoteRefAllowList(allowList); parseOptions.setRemoteRefBlockList(blockList); @@ -3235,7 +3237,7 @@ public void test31SafeURLResolvingWithTurnedOffSafeResolving() { parseOptions.setResolveFully(true); parseOptions.setSafelyResolveURL(false); List allowList = Collections.emptyList(); - List blockList = Arrays.asList("petstore3.swagger.io"); + List blockList = Collections.singletonList("petstore3.swagger.io"); parseOptions.setRemoteRefAllowList(allowList); parseOptions.setRemoteRefBlockList(blockList); @@ -3268,7 +3270,7 @@ public void test31SafeURLResolvingWithLocalhost() { ParseOptions parseOptions = new ParseOptions(); parseOptions.setResolveFully(true); parseOptions.setSafelyResolveURL(true); - List blockList = Arrays.asList("petstore.swagger.io"); + List blockList = Collections.singletonList("petstore.swagger.io"); parseOptions.setRemoteRefBlockList(blockList); String error = "URL is part of the explicit denylist. URL [https://petstore.swagger.io/v2/swagger.json]"; diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/ParserDeduplicationParameterTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/ParserDeduplicationParameterTest.java new file mode 100644 index 0000000000..568d7f616b --- /dev/null +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/ParserDeduplicationParameterTest.java @@ -0,0 +1,133 @@ +package io.swagger.v3.parser.test; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.parser.OpenAPIV3Parser; +import io.swagger.v3.parser.core.models.ParseOptions; +import org.testng.annotations.Test; + +import java.util.List; +import java.util.stream.Collectors; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +public class ParserDeduplicationParameterTest { + + @Test + public void testIssue2102TwoRefsSameNameDifferentIn31() { + ParseOptions options = new ParseOptions(); + options.setResolve(true); + options.setResolveCombinators(true); + options.setResolveFully(true); + + OpenAPI openAPI = new OpenAPIV3Parser() + .read("issue-2102/openapi31.json", null, options); + + List params = + openAPI.getPaths() + .get("/myoperation") + .getGet() + .getParameters(); + + assertEquals(params.size(), 2); + List paramIns = params.stream().map(Parameter::getIn).collect(Collectors.toList()); + assertTrue(paramIns.contains("query")); + assertTrue(paramIns.contains("header")); + } + + + @Test(description = "Duplicated parameter name with different locations") + public void testDuplicatedParameterNameFromRef() { + OpenAPIV3Parser openApiParser = new OpenAPIV3Parser(); + ParseOptions options = new ParseOptions(); + options.setResolve(true); + options.setFlatten(true); + OpenAPI openAPI = openApiParser.read("issue-2102/openapi30.json", null, options); + + assertEquals(openAPI.getPaths().get("/myoperation").getGet().getParameters().size(), 2); + assertEquals((int) openAPI.getPaths().get("/myoperation").getGet().getParameters().stream().filter(param -> param.getName().equals("myParam")).count(), 2); + } + + @Test(description = "Duplicated parameter name with different locations") + public void testDuplicatedParameterNameFromRefResolveFullyResolveCombinators() { + OpenAPIV3Parser openApiParser = new OpenAPIV3Parser(); + ParseOptions options = new ParseOptions(); + options.setResolve(true); + options.setResolveCombinators(true); + options.setResolveFully(true); + OpenAPI openAPI = openApiParser.read("issue-2102/openapi30.json", null, options); + + assertEquals(openAPI.getPaths().get("/myoperation").getGet().getParameters().size(), 2); + assertEquals((int) openAPI.getPaths().get("/myoperation").getGet().getParameters().stream().filter(param -> param.getName().equals("myParam")).count(), 2); + } + + @Test + public void testInlineAndRefSameNameDifferentIn() { + ParseOptions options = new ParseOptions(); + options.setResolve(true); + options.setResolveFully(true); + + OpenAPI openAPI = new OpenAPIV3Parser() + .read("issue-2102/openapi30mixedRef.yaml", null, options); + + List params = + openAPI.getPaths() + .get("/mixed") + .getGet() + .getParameters(); + + assertEquals(params.size(), 2); + List paramDescriptions = params.stream() + .map(p -> p.getIn() + ":" + p.getName()) + .collect(Collectors.toList()); + assertTrue(paramDescriptions.contains("query:myParam")); + assertTrue(paramDescriptions.contains("header:myParam")); + } + + @Test + public void testInlineAndRefSameNameSameIn() { + ParseOptions options = new ParseOptions(); + options.setResolve(true); + options.setResolveFully(true); + + OpenAPI openAPI = new OpenAPIV3Parser() + .read("issue-2102/openapi30mixedRef.yaml", null, options); + + List params = + openAPI.getPaths() + .get("/mixed") + .getGet() + .getParameters(); + + assertEquals(params.size(), 2); + List paramDescriptions = params.stream() + .map(p -> p.getIn() + ":" + p.getName()) + .collect(Collectors.toList()); + assertTrue(paramDescriptions.contains("query:myParam")); + assertTrue(paramDescriptions.contains("header:myParam")); + } + + @Test + public void testOperationLevel_sameNameSameIn_refOverridesInline() { + ParseOptions options = new ParseOptions(); + options.setResolve(true); + options.setResolveFully(true); + + OpenAPI openAPI = new OpenAPIV3Parser() + .read("issue-2102/openapi30sameNameSameLocation.yaml", null, options); + + List params = + openAPI.getPaths() + .get("/duplicate") + .getGet() + .getParameters(); + + assertEquals(params.size(), 1); + + Parameter p = params.get(0); + assertEquals(p.getName(), "myParam"); + assertEquals(p.getIn(), "query"); + assertEquals(p.getSchema().getFormat(), "date-time"); + } +} diff --git a/modules/swagger-parser-v3/src/test/resources/issue-2102/openapi30.json b/modules/swagger-parser-v3/src/test/resources/issue-2102/openapi30.json new file mode 100644 index 0000000000..6a921b73bb --- /dev/null +++ b/modules/swagger-parser-v3/src/test/resources/issue-2102/openapi30.json @@ -0,0 +1,35 @@ +{ + "openapi": "3.0.0", + "paths": { + "/myoperation": { + "get": { + "parameters": [ + {"$ref": "#/components/parameters/schemaParam1"}, + {"$ref": "#/components/parameters/schemaParam2"} + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }}}}}}}, + "components": { + "parameters": { + "schemaParam1": { + "name": "myParam", + "in": "query", + "schema": { + "type": "string" + } + }, + "schemaParam2": { + "name": "myParam", + "in": "header", + "schema": { + "type": "string" + } + }}} +} \ No newline at end of file diff --git a/modules/swagger-parser-v3/src/test/resources/issue-2102/openapi30mixedRef.yaml b/modules/swagger-parser-v3/src/test/resources/issue-2102/openapi30mixedRef.yaml new file mode 100644 index 0000000000..8f9d5bd939 --- /dev/null +++ b/modules/swagger-parser-v3/src/test/resources/issue-2102/openapi30mixedRef.yaml @@ -0,0 +1,18 @@ +openapi: 3.0.0 +paths: + /mixed: + get: + parameters: + - in: query + name: myParam + schema: { type: string } + - $ref: '#/components/parameters/headerMyParam' + responses: + '200': + description: OK +components: + parameters: + headerMyParam: + in: header + name: myParam + schema: { type: string } diff --git a/modules/swagger-parser-v3/src/test/resources/issue-2102/openapi30sameNameSameLocation.yaml b/modules/swagger-parser-v3/src/test/resources/issue-2102/openapi30sameNameSameLocation.yaml new file mode 100644 index 0000000000..9bf68bb430 --- /dev/null +++ b/modules/swagger-parser-v3/src/test/resources/issue-2102/openapi30sameNameSameLocation.yaml @@ -0,0 +1,18 @@ +openapi: 3.0.0 +paths: + /duplicate: + get: + parameters: + - in: query + name: myParam + schema: { type: string, format: uuid } + - $ref: '#/components/parameters/queryMyParam' + responses: + '200': + description: OK +components: + parameters: + queryMyParam: + in: query + name: myParam + schema: { type: string, format: date-time } diff --git a/modules/swagger-parser-v3/src/test/resources/issue-2102/openapi31.json b/modules/swagger-parser-v3/src/test/resources/issue-2102/openapi31.json new file mode 100644 index 0000000000..2809311ca9 --- /dev/null +++ b/modules/swagger-parser-v3/src/test/resources/issue-2102/openapi31.json @@ -0,0 +1,35 @@ +{ + "openapi": "3.1.0", + "paths": { + "/myoperation": { + "get": { + "parameters": [ + {"$ref": "#/components/parameters/schemaParam1"}, + {"$ref": "#/components/parameters/schemaParam2"} + ], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "type": "string" + } + }}}}}}}, + "components": { + "parameters": { + "schemaParam1": { + "name": "myParam", + "in": "query", + "schema": { + "type": "string" + } + }, + "schemaParam2": { + "name": "myParam", + "in": "header", + "schema": { + "type": "string" + } + }}} +} \ No newline at end of file From dddcf0fea6213597f813c7c6ed93c7487ecf3f07 Mon Sep 17 00:00:00 2001 From: "sonatypeoss[bot]" <68616245+sonatypeoss[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 13:39:25 +0100 Subject: [PATCH 4/4] prepare release 2.1.36 (#2251) Co-authored-by: ewaostrowska --- README.md | 2 +- modules/swagger-parser-cli/pom.xml | 4 ++-- modules/swagger-parser-core/pom.xml | 2 +- modules/swagger-parser-safe-url-resolver/pom.xml | 2 +- modules/swagger-parser-v2-converter/pom.xml | 2 +- modules/swagger-parser-v3/pom.xml | 2 +- modules/swagger-parser/pom.xml | 2 +- pom.xml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index a0a82a1099..c408056591 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ You can include this library from Sonatype OSS for SNAPSHOTS, or Maven central f io.swagger.parser.v3 swagger-parser - 2.1.35 + 2.1.36 ``` diff --git a/modules/swagger-parser-cli/pom.xml b/modules/swagger-parser-cli/pom.xml index 09c8b5aa3f..9a8d1a1a05 100644 --- a/modules/swagger-parser-cli/pom.xml +++ b/modules/swagger-parser-cli/pom.xml @@ -5,7 +5,7 @@ swagger-parser-project io.swagger.parser.v3 - 2.1.36-SNAPSHOT + 2.1.36 ../.. 4.0.0 @@ -91,7 +91,7 @@ io.swagger.parser.v3 swagger-parser-v3 - 2.1.36-SNAPSHOT + 2.1.36 compile diff --git a/modules/swagger-parser-core/pom.xml b/modules/swagger-parser-core/pom.xml index 062f088038..70f0b6b1d6 100644 --- a/modules/swagger-parser-core/pom.xml +++ b/modules/swagger-parser-core/pom.xml @@ -3,7 +3,7 @@ io.swagger.parser.v3 swagger-parser-project - 2.1.36-SNAPSHOT + 2.1.36 ../.. 4.0.0 diff --git a/modules/swagger-parser-safe-url-resolver/pom.xml b/modules/swagger-parser-safe-url-resolver/pom.xml index 3b9629c0ec..40ea10e494 100644 --- a/modules/swagger-parser-safe-url-resolver/pom.xml +++ b/modules/swagger-parser-safe-url-resolver/pom.xml @@ -6,7 +6,7 @@ io.swagger.parser.v3 swagger-parser-project - 2.1.36-SNAPSHOT + 2.1.36 ../../pom.xml diff --git a/modules/swagger-parser-v2-converter/pom.xml b/modules/swagger-parser-v2-converter/pom.xml index 848c399aae..0cf1273264 100644 --- a/modules/swagger-parser-v2-converter/pom.xml +++ b/modules/swagger-parser-v2-converter/pom.xml @@ -3,7 +3,7 @@ io.swagger.parser.v3 swagger-parser-project - 2.1.36-SNAPSHOT + 2.1.36 ../.. 4.0.0 diff --git a/modules/swagger-parser-v3/pom.xml b/modules/swagger-parser-v3/pom.xml index 4788cef4ba..bdcff18800 100644 --- a/modules/swagger-parser-v3/pom.xml +++ b/modules/swagger-parser-v3/pom.xml @@ -3,7 +3,7 @@ io.swagger.parser.v3 swagger-parser-project - 2.1.36-SNAPSHOT + 2.1.36 ../.. 4.0.0 diff --git a/modules/swagger-parser/pom.xml b/modules/swagger-parser/pom.xml index 8348eb39c8..c517487bcc 100644 --- a/modules/swagger-parser/pom.xml +++ b/modules/swagger-parser/pom.xml @@ -3,7 +3,7 @@ io.swagger.parser.v3 swagger-parser-project - 2.1.36-SNAPSHOT + 2.1.36 ../.. 4.0.0 diff --git a/pom.xml b/pom.xml index 11572dacf9..e2849082ae 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 io.swagger.parser.v3 swagger-parser-project - 2.1.36-SNAPSHOT + 2.1.36 pom swagger-parser-project swagger-parser-project