Closed rmelasavvi closed 2 years ago
FWIW, here's how I resolved it for our internal use. Solution is not the cleanest, but does point to locations in the code where you might implement a fix
diff --git a/src/components/Schema/DiscriminatorDropdown.tsx b/src/components/Schema/DiscriminatorDropdown.tsx
index d3290a2a..0d155861 100644
--- a/src/components/Schema/DiscriminatorDropdown.tsx
+++ b/src/components/Schema/DiscriminatorDropdown.tsx
@@ -31,9 +31,11 @@ export class DiscriminatorDropdown extends React.Component<{
return null;
}
+ const discriminatorProp = parent.discriminatorProp
+
const options = parent.oneOf.map((subSchema, idx) => {
return {
- value: subSchema.title,
+ value: subSchema.discriminant(discriminatorProp),
idx,
};
});
diff --git a/src/services/models/MediaType.ts b/src/services/models/MediaType.ts
index 25dae807..2a1e6e20 100644
--- a/src/services/models/MediaType.ts
+++ b/src/services/models/MediaType.ts
@@ -63,10 +63,9 @@ export class MediaTypeModel {
const sample = Sampler.sample(subSchema.rawSchema as any, samplerOptions, parser.spec);
if (this.schema.discriminatorProp && typeof sample === 'object' && sample) {
- sample[this.schema.discriminatorProp] = subSchema.title;
+ sample[this.schema.discriminatorProp] = subSchema.discriminant(this.schema.discriminatorProp)
}
-
- this.examples[subSchema.title] = new ExampleModel(
+ this.examples[subSchema.discriminant()] = new ExampleModel(
parser,
{
value: sample,
diff --git a/src/services/models/Schema.ts b/src/services/models/Schema.ts
index b155d254..32294847 100644
--- a/src/services/models/Schema.ts
+++ b/src/services/models/Schema.ts
@@ -102,6 +102,26 @@ export class SchemaModel {
this.activeOneOf = idx;
}
+ discriminant(propName?): string {
+
+ if (!propName) {
+ propName = this.schema.discriminator?.propertyName
+
+ }
+ if (!propName) {
+ return this.title
+ }
+ const properties = this.schema.properties
+
+ if (!properties) {
+ return this.title
+ }
+
+ const prop = (properties[propName] || null)
+
+ return prop && prop.enum && prop.enum.length && prop.enum[0] || this.title
+ }
+
hasType(type: string) {
return this.type === type || (Array.isArray(this.type) && this.type.includes(type));
}
I checked your PR.
You should define mapping in this case, extracting value from enum is error-prone, it may be on different levels, e.g. it may have allOf. So it's not universal solution.
Car:
allOf:
- $ref: "#/components/schemas/Vehicle"
- type: object
properties:
vehicle_type:
allOf:
- enum:
- automobile
has_4_wheel_drive:
type: boolean
Use mapping instead, e.g.
components:
schemas:
Vehicle:
type: object
required:
- id
- vehicle_type
properties:
id:
type: integer
model:
type: string
name:
type: string
vehicle_type:
type: string
discriminator:
propertyName: vehicle_type
mapping:
automobile: '#/components/schemas/Automobile'
airplane: '#/components/schemas/Airplane'
Describe the bug
Happens if I define a "Vehicle", with a discriminator property of "vehicle_type", and then derive a "Car", with "vehicle_type: automobile". The discriminator dropdowns and the sample requests ignore the values I've provided and use "Car" instead of the "automobile" value I've specified.
Expected behavior
If I define a Vehicle object with a discriminator propertyName of 'vehicle_type', and then in subclass Car I provide a value of 'automobile', then I expect the discriminator dropdowns, and the vehicle_type in the sample, to display "automobile", not "Car".
Minimal reproducible OpenAPI snippet(if possible)
Screenshots Problem - I expect to see "automobile" and "airplane", not "Car" and "Plane" in the dropdowns and in the example.
Expected ( I've only fixed the sample component -- not the dropdowns yet ):