Too many cases generated when oneOf discriminator has explicit mappings
JanC opened this issue · comments
Hi,
I noticed that when I set an explicit mappings to a discriminator
, the default mapping remain in the generated code when decoding.
Given this spec
SingleAnimal:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
discriminator:
propertyName: type
mapping:
woof: '#/components/schemas/Dog'
dog: '#/components/schemas/Dog'
cat: '#/components/schemas/Cat'
The generated SingeAnimal.swift
contains
As you can see, the switch on the discriminator
value contains both the explicit mappings cat
dog
, woof
values but also what seems to be the implicit mappings by the name of the reference Cat
and Dog
.
Since I supply explicit mappings, I would expect only the explicit ones to be present:
let discriminator: String = try container.decode("type")
switch discriminator {
case "cat":
self = .cat(try Cat(from: decoder))
case "dog":
self = .dog(try Dog(from: decoder))
case "woof":
self = .dog(try Dog(from: decoder))
default:
throw DecodingError.dataCorrupted(DecodingError.Context.init(codingPath: decoder.codingPath, debugDescription: "Couldn't find type to decode with discriminator \(discriminator)"))
}
I think that if we detect an explicit mapping for a type, we should remove the implicit one in CodeFormatter.swift#L216
So just adding mapping.removeValue(forKey: reference.name)
here would work:
if let discriminatorMapping = groupSchema.discriminator?.mapping {
for (key, value) in discriminatorMapping {
let reference = Reference<Schema>(value)
// remove the implicit mapping for that reference
mapping.removeValue(forKey: reference.name)
// add the explicit one
mapping[key] = getReferenceContext(reference)
}
}
@yonaskolb any thoughts? If you agree with the approach, I can open a PR.
I used the specs.yaml from the repo but for reference I put the relevant part here:
openapi: 3.1.0
info:
title: MyAPI
version: '1.0'
servers:
- url: 'http://localhost:3000'
paths:
/pets/:
parameters: []
get:
tags: []
responses:
'200':
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/SingleAnimal'
operationId: get-objects
components:
schemas:
Animal:
type: object
properties:
animal:
type: string
SingleAnimal:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
discriminator:
propertyName: type
mapping:
woof: '#/components/schemas/Dog'
dog: '#/components/schemas/Dog'
cat: '#/components/schemas/Cat'
Cat:
allOf:
- $ref: '#/components/schemas/Animal'
- type: object
properties:
meows:
type: boolean
Dog:
allOf:
- $ref: '#/components/schemas/Animal'
- type: object
properties:
barks:
type: boolean