Repository: swagger-api/swagger-parser
Pull request #2203 (2025-06-18 09:21:02)

fix $ref parsing when it contains dot inside component name
Before merge:
- [ ] Bump swagger-core and update it's version in pom


Patch:
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 b4ee3953..cd00224c 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
@@ -794,7 +794,6 @@ public final class ExternalRefProcessor {
         if(renamedRef != null) {
             return renamedRef;
         }
-
         final Parameter parameter = cache.loadRef($ref, refFormat, Parameter.class);
 
         if(parameter == null) {
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 100846e7..efdace6d 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
@@ -43,8 +43,9 @@ public class ParameterProcessor {
         if($ref != null){
             RefFormat refFormat = computeRefFormat(parameter.get$ref());
             if (isAnExternalRefFormat(refFormat)){
-                final String newRef = externalRefProcessor.processRefToExternalParameter($ref, refFormat);
+                String newRef = externalRefProcessor.processRefToExternalParameter($ref, refFormat);
                 if (newRef != null) {
+                    newRef = "#/components/parameters/" + newRef;
                     parameter.set$ref(newRef);
                 }
             }
@@ -75,11 +76,9 @@ public class ParameterProcessor {
     }
 
    public List<Parameter> processParameters(List<Parameter> parameters) {
-
         if (parameters == null) {
             return null;
         }
-
         final List<Parameter> processedPathLevelParameters = new ArrayList<>();
         final List<Parameter> refParameters = new ArrayList<>();
 
@@ -92,7 +91,6 @@ public class ParameterProcessor {
                     //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) {
                     // can't resolve it!
                     processedPathLevelParameters.add(parameter);
diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/PathsProcessor.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/PathsProcessor.java
index 94cecd67..1aacbe7d 100644
--- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/PathsProcessor.java
+++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/PathsProcessor.java
@@ -65,11 +65,8 @@ public class PathsProcessor {
             PathItem pathItem = pathMap.get(pathStr);
 
             if (pathItem.get$ref() != null) {
-
                 PathItem resolvedPath = processReferencePath(pathItem);
-
                 String pathRef = pathItem.get$ref().split("#")[0];
-
                 if (resolvedPath != null) {
                     updateRefs(resolvedPath, pathRef);
                     //we need to put the resolved path into swagger object
@@ -84,7 +81,6 @@ public class PathsProcessor {
             final List<Parameter> processedPathParameters = parameterProcessor.processParameters(pathItem.getParameters());
             pathItem.setParameters(processedPathParameters);
 
-
             final Map<PathItem.HttpMethod, Operation> operationMap = pathItem.readOperationsMap();
 
             for (PathItem.HttpMethod httpMethod : operationMap.keySet()) {
diff --git a/pom.xml b/pom.xml
index cadc10ff..3e613123 100644
--- a/pom.xml
+++ b/pom.xml
@@ -372,7 +372,7 @@
         <swagger-parser-v2-version>1.0.75</swagger-parser-v2-version>
         <commons-io-version>2.19.0</commons-io-version>
         <slf4j-version>2.0.9</slf4j-version>
-        <swagger-core-version>2.2.32</swagger-core-version>
+        <swagger-core-version>2.2.34</swagger-core-version>
         <swagger-core-v2-version>1.6.16</swagger-core-v2-version>
         <junit-version>4.13.2</junit-version>
         <testng-version>7.11.0</testng-version>


Test patch:
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 a3737f63..c8dac007 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
@@ -7,6 +7,8 @@ import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+
+import io.swagger.v3.parser.core.models.SwaggerParseResult;
 import org.junit.Before;
 import org.junit.Test;
 import org.testng.Assert;
@@ -33,6 +35,31 @@ public class OpenAPIV3RefTest {
         options.setResolve(true);
         oas = new OpenAPIV3Parser().read("oas3-refs-test/openapi.json", null, options);
     }
+
+    @Test
+    public void testRefContainingDot() {
+        ParseOptions options = new ParseOptions();
+        options.setResolve(true);
+        SwaggerParseResult result = new OpenAPIV3Parser().readLocation("resolve-dot-containing-ref/standaloneSpec.yaml", null, options);
+
+        Assert.assertNotNull(result.getOpenAPI());
+        Assert.assertTrue(result.getMessages().isEmpty(), "No error messages should be present");
+        Assert.assertNotNull(result.getOpenAPI().getPaths().get("/endpoint").getGet().getParameters());
+        Assert.assertEquals(result.getOpenAPI().getPaths().get("/endpoint").getGet().getParameters().get(0).getName(), "FbtPrincipalIdentity");
+    }
+
+    @Test
+    public void testExternalRefContainingDot() {
+        ParseOptions options = new ParseOptions();
+        options.setResolve(true);
+        SwaggerParseResult result = new OpenAPIV3Parser().readLocation("resolve-dot-containing-ref/externalRefSpec.yaml", null, options);
+
+        Assert.assertNotNull(result.getOpenAPI());
+        Assert.assertTrue(result.getMessages().isEmpty(), "No error messages should be present");
+        Assert.assertNotNull(result.getOpenAPI().getPaths().get("/endpoint").getGet().getParameters());
+        Assert.assertEquals(result.getOpenAPI().getPaths().get("/endpoint").getGet().getParameters().get(0).getName(), "FbtPrincipalIdentity");
+    }
+
     @Test
     public void testParameterExampleRefProcessed() {
         String paramName = "correlation_id";
@@ -85,3 +112,4 @@ public class OpenAPIV3RefTest {
         assertEquals(adopterAlias.getItems().getAllOf().size(), 2, "Processed schemas items");
     }
 }
+
diff --git a/modules/swagger-parser-v3/src/test/resources/resolve-dot-containing-ref/externalRefDomain.yaml b/modules/swagger-parser-v3/src/test/resources/resolve-dot-containing-ref/externalRefDomain.yaml
new file mode 100644
index 00000000..ae69b738
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/resolve-dot-containing-ref/externalRefDomain.yaml
@@ -0,0 +1,17 @@
+openapi: 3.0.0
+info:
+  title: Test domain
+  description: Domain for testing
+  version: '1.0.0'
+components:
+  parameters:
+    FbtPrincipalIdentity_V3.1:
+      name: FbtPrincipalIdentity
+      in: query
+      schema:
+        type: string
+    FbtPrincipalIdentity_V31:
+      name: FbtPrincipalIdentity
+      in: query
+      schema:
+        type: string
\ No newline at end of file
diff --git a/modules/swagger-parser-v3/src/test/resources/resolve-dot-containing-ref/externalRefSpec.yaml b/modules/swagger-parser-v3/src/test/resources/resolve-dot-containing-ref/externalRefSpec.yaml
new file mode 100644
index 00000000..e80536e3
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/resolve-dot-containing-ref/externalRefSpec.yaml
@@ -0,0 +1,26 @@
+openapi: 3.0.0
+info:
+  title: Test API
+  version: 1.0.0
+  description: Test API with dot-containing $ref
+paths:
+  /endpoint:
+    get:
+      summary: summary
+      operationId: id
+      description: Test description
+      parameters:
+        - $ref: 'resolve-dot-containing-ref/externalRefDomain.yaml#/components/parameters/FbtPrincipalIdentity_V3.1'
+      responses:
+        '200':
+          description: get description
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/item'
+components:
+  schemas:
+    item:
+      type: object
\ No newline at end of file
diff --git a/modules/swagger-parser-v3/src/test/resources/resolve-dot-containing-ref/standaloneSpec.yaml b/modules/swagger-parser-v3/src/test/resources/resolve-dot-containing-ref/standaloneSpec.yaml
new file mode 100644
index 00000000..870a4338
--- /dev/null
+++ b/modules/swagger-parser-v3/src/test/resources/resolve-dot-containing-ref/standaloneSpec.yaml
@@ -0,0 +1,37 @@
+openapi: 3.0.0
+info:
+  title: Test API
+  version: 1.0.0
+  description: Test API with dot-containing $ref
+paths:
+  /endpoint:
+    get:
+      summary: summary
+      operationId: id
+      description: Test description
+      parameters:
+        - $ref: '#/components/parameters/FbtPrincipalIdentity_V3.1'
+      responses:
+        '200':
+          description: get description
+          content:
+            application/json:
+              schema:
+                type: array
+                items:
+                  $ref: '#/components/schemas/item'
+components:
+  parameters:
+    FbtPrincipalIdentity_V3.1:
+      name: FbtPrincipalIdentity
+      in: query
+      schema:
+        type: string
+    FbtPrincipalIdentity_V31:
+      name: FbtPrincipalIdentity
+      in: query
+      schema:
+        type: string
+  schemas:
+    item:
+      type: object
\ No newline at end of file