Skip to content

Commit 18d5450

Browse files
committed
Normalize relative ref paths to avoid duplicating schemas
Currently, if an OpenAPI spec contains multiple relative refs to the same file, but those refs are located in different files and use different relative paths to reach the one file, swagger-parser will create a separate, duplicate schema for each relative path rather than reusing the same schema across all equivalent paths. For example, given a spec with the following refs: - In spec root directory, `$ref: ./components/schemas/Thing.yaml` - In components/paths subdirectory, `$ref: ../../components/schemas/Thing.yaml` The parser will produce a `Thing` and a `Thing_1` schema object instead of reusing `Thing` for the second, equivalent reference. This updates the ref processor to resolve relative paths before processing relative refs in order to produce a single `Thing` schema that is reused for all equivalent references.
1 parent 0ab2e8a commit 18d5450

File tree

364 files changed

+15103
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

364 files changed

+15103
-1
lines changed

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import io.swagger.v3.parser.ResolverCache;
3030
import io.swagger.v3.parser.models.RefFormat;
3131
import io.swagger.v3.parser.models.RefType;
32+
import io.swagger.v3.parser.util.RefUtils;
33+
3234
import org.apache.commons.io.FilenameUtils;
3335
import org.apache.commons.lang3.StringUtils;
3436
import org.slf4j.LoggerFactory;
@@ -86,6 +88,18 @@ public String processRefToExternalSchema(String $ref, RefFormat refFormat) {
8688
return renamedRef;
8789
}
8890

91+
RefFormat format = computeRefFormat($ref);
92+
if (format.equals(RefFormat.RELATIVE)) {
93+
String normalizedRef = Paths.get($ref).normalize().toString();
94+
System.out.println("Normalized " + $ref + " to " + normalizedRef);
95+
renamedRef = cache.getRenamedRef($ref);
96+
if (renamedRef != null) {
97+
return renamedRef;
98+
} else {
99+
$ref = normalizedRef;
100+
}
101+
}
102+
89103
final Schema schema = cache.loadRef($ref, refFormat, Schema.class);
90104

91105
if(schema == null) {

modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIV3ParserTest.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1953,6 +1953,18 @@ public void testRelativePath2() {
19531953
Assert.assertEquals(readResult.getOpenAPI().getPaths().get("/pet/findByTags").getGet().getResponses().get("default").getContent().get("application/json").getSchema().get$ref(), "#/components/schemas/ErrorModel");
19541954
}
19551955

1956+
@Test
1957+
public void testExternalRefsNormalization() throws Exception {
1958+
ParseOptions options = new ParseOptions();
1959+
options.setResolve(true);
1960+
SwaggerParseResult result = new OpenAPIV3Parser()
1961+
.readLocation("src/test/resources/oas3.fetched/openapi3.yaml", null, options);
1962+
1963+
OpenAPI openAPI = result.getOpenAPI();
1964+
Schema localModel = openAPI.getComponents().getSchemas().get("Event_2");
1965+
assertNull(localModel);
1966+
}
1967+
19561968
private OpenAPI doRelativeFileTest(String location) {
19571969
OpenAPIV3Parser parser = new OpenAPIV3Parser();
19581970
ParseOptions options = new ParseOptions();
@@ -3298,4 +3310,4 @@ public void testIssue2081() {
32983310
assertEquals(openAPI.getComponents().getSchemas().get("PetCreate").getRequired().size(), 1);
32993311
assertEquals(openAPI.getComponents().getSchemas().get("PetCreate").getProperties().size(), 2);
33003312
}
3301-
}
3313+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
description: Search by hostname, description, short_id, reservation short_id, tags, plan name, plan slug, facility code, facility name, operating system name, operating system slug, IP addresses.
2+
in: query
3+
name: search
4+
schema:
5+
type: string
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
description: |-
2+
Nested attributes to exclude. Excluded objects will return only the href
3+
attribute. Attribute names can be dotted (up to 3 levels) to exclude deeply
4+
nested objects.
5+
in: query
6+
name: exclude
7+
schema:
8+
items:
9+
type: string
10+
type: array
11+
style: form
12+
explode: false
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
description: |-
2+
Nested attributes to include. Included objects will return their full
3+
attributes. Attribute names can be dotted (up to 3 levels) to included deeply
4+
nested objects.
5+
in: query
6+
name: include
7+
schema:
8+
items:
9+
type: string
10+
type: array
11+
style: form
12+
explode: false
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
description: Page to return
2+
in: query
3+
name: page
4+
schema:
5+
default: 1
6+
format: int32
7+
maximum: 100000
8+
minimum: 1
9+
type: integer
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
description: Items returned per page
2+
in: query
3+
name: per_page
4+
schema:
5+
default: 10
6+
format: int32
7+
maximum: 1000
8+
minimum: 1
9+
type: integer
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
description: Filter results by name.
2+
in: query
3+
name: name
4+
schema:
5+
type: string
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
content:
2+
application/json:
3+
schema:
4+
oneOf:
5+
- $ref: '../schemas/DedicatedPortCreateInput.yaml'
6+
- $ref: '../schemas/VlanFabricVcCreateInput.yaml'
7+
- $ref: '../schemas/VrfFabricVcCreateInput.yaml'
8+
description: Dedicated port or shared interconnection (also known as Fabric VC) creation request
9+
required: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
content:
2+
application/json:
3+
schema:
4+
$ref: '../schemas/InvitationInput.yaml'
5+
description: Invitation to create
6+
required: true

0 commit comments

Comments
 (0)