Skip to content

Commit 676c821

Browse files
authored
Fix discriminator key and value were getting mixed up resulting in DuplicateKeyError (#2222)
1 parent ef2cf16 commit 676c821

File tree

5 files changed

+109
-2
lines changed

5 files changed

+109
-2
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ private void processSchema(Schema property, String file) {
250250
ComposedSchema composed = (ComposedSchema) property;
251251
final Map<String, String> refMap = Optional.ofNullable(composed.getDiscriminator())
252252
.map(Discriminator::getMapping).orElse(Collections.emptyMap()).entrySet()
253-
.stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
253+
.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
254254
Map<String, Schema> refCache = (!refMap.isEmpty() &&
255255
(composed.getAnyOf() != null || composed.getOneOf() != null)) ? Stream.of(
256256
composed.getAnyOf(), composed.getOneOf()
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package io.swagger.v3.parser.test;
2+
3+
import io.swagger.v3.core.util.Json;
4+
import io.swagger.v3.oas.models.media.Discriminator;
5+
import io.swagger.v3.oas.models.responses.ApiResponse;
6+
import io.swagger.v3.parser.OpenAPIV3Parser;
7+
import io.swagger.v3.parser.core.models.ParseOptions;
8+
import io.swagger.v3.parser.core.models.SwaggerParseResult;
9+
import org.junit.Test;
10+
11+
import static org.junit.Assert.assertEquals;
12+
13+
public class Issue2222Test {
14+
15+
@Test
16+
public void shouldMapSameEntitiesToDifferentDiscriminatorValues() {
17+
ParseOptions options = new ParseOptions();
18+
options.setResolveFully(true);
19+
SwaggerParseResult result = new OpenAPIV3Parser().readLocation("issue-2222/openapi.yaml", null, options);
20+
21+
// No error/warning messages should be present, especially Duplicate key ones
22+
assertEquals(0, result.getMessages().size());
23+
assertEquals(1, result.getOpenAPI().getPaths().size());
24+
ApiResponse response = result.getOpenAPI().getPaths().get("/mypath").readOperations().get(0).getResponses().get("200");
25+
Discriminator discriminator = response.getContent().get("application/json").getSchema().getItems().getDiscriminator();
26+
assertEquals("discriminatorProperty", discriminator.getPropertyName());
27+
assertEquals("#/components/schemas/TypeA", discriminator.getMapping().get("ONE"));
28+
assertEquals("#/components/schemas/TypeB", discriminator.getMapping().get("TWO"));
29+
assertEquals("#/components/schemas/TypeB", discriminator.getMapping().get("THREE"));
30+
assertEquals("#/components/schemas/TypeB", discriminator.getMapping().get("FOUR"));
31+
assertEquals("#/components/schemas/TypeB", discriminator.getMapping().get("FIVE"));
32+
}
33+
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,11 @@ public void testDiscriminatorMappingRefsUpdated() {
8383
Set<String> allOfs = ((List<Schema>)reqSchema.getAnyOf())
8484
.stream().map(Schema::get$ref).collect(Collectors.toSet());
8585
assertTrue(allOfs.stream().allMatch(s -> s.contains(COMPONENTS_SCHEMAS_REF)),"Schema mappings are processed");
86-
assertTrue(allOfs.containsAll(discriminator),"Discriminator mappings are updated");
86+
Set<String> allOfsNames = allOfs.stream()
87+
.map(of -> of.split("/schemas/")[1]).collect(Collectors.toSet());
88+
Collection<String> discriminatorNames = discriminator.stream().map(of -> of.split("/schemas/")[1]
89+
.replace(".json","")).collect(Collectors.toSet());
90+
assertTrue(allOfsNames.containsAll(discriminatorNames),"Discriminator mappings are updated");
8791

8892
}
8993

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
get:
2+
summary: Get all objects
3+
operationId: getObjects
4+
responses:
5+
'200':
6+
description: "List of all the objects."
7+
content:
8+
application/json:
9+
schema:
10+
type: array
11+
items:
12+
oneOf:
13+
- $ref: '#/components/schemas/TypeA'
14+
- $ref: '#/components/schemas/TypeB'
15+
discriminator:
16+
propertyName: discriminatorProperty
17+
mapping:
18+
ONE: '#/components/schemas/TypeA'
19+
TWO: '#/components/schemas/TypeB'
20+
THREE: '#/components/schemas/TypeB'
21+
FOUR: '#/components/schemas/TypeB'
22+
FIVE: '#/components/schemas/TypeB'
23+
24+
components:
25+
schemas:
26+
BaseType:
27+
type: object
28+
required:
29+
- discriminatorProperty
30+
properties:
31+
discriminatorProperty:
32+
type: string
33+
description: A property used to determine the concrete object type.
34+
enum: [ONE, TWO, THREE, FOUR, FIVE]
35+
id:
36+
type: string
37+
description: Unique identifier for the object.
38+
39+
TypeA:
40+
allOf:
41+
- $ref: '#/components/schemas/BaseType'
42+
- type: object
43+
properties:
44+
discriminatorProperty:
45+
type: string
46+
enum: [ONE]
47+
name:
48+
type: string
49+
description: A name specific to TypeA.
50+
51+
TypeB:
52+
allOf:
53+
- $ref: '#/components/schemas/BaseType'
54+
- type: object
55+
properties:
56+
discriminatorProperty:
57+
type: string
58+
enum: [TWO, THREE, FOUR, FIVE]
59+
value:
60+
type: number
61+
description: A numeric value specific to TypeB.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
openapi: 3.0.0
2+
info:
3+
title: Example API
4+
version: 1.0.0
5+
description: Example API demonstrating polymorphic response with external schemas.
6+
7+
paths:
8+
/mypath:
9+
$ref: './mypath.yaml'

0 commit comments

Comments
 (0)