yonaskolb / SwagGen

OpenAPI/Swagger 3.0 Parser and Swift code generator

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

oneOf does not generate cases when the type is object

JanC opened this issue · comments

Hi,
I noticed that the oneOf keyword seems to be ignored when the schema contains also the type: object:

In the below example, the SingleAnimal is taken from the spec.yaml but I added the type: object.

The generated code is a struct

public struct SingleAnimal: Codable, Equatable {
    public init() {}

    public init(from _: Decoder) throws {}
}

while I would expect it to be a enum

public enum SingleAnimal: Codable, Equatable {
    case cat(Cat)
    case dog(Dog)

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: StringCodingKey.self)
        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 "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(codingPath: decoder.codingPath, debugDescription: "Couldn't find type to decode with discriminator \(discriminator)"))
        }
    }
}
SingleAnimal:
  type: object   #This was added
  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
Animal:
    type: object
    properties:
      animal:
        type: string

I believe it is due to this part when decoding the schema dictionary. If the schema parses as DataType we assume it's actually a datatype and don't check further for the allOf, oneOf and allOf.

The open api validation parses such a schema as a oneOf so it seems those specific types have priority over the type: object.

Would it make sense to change the parsing below and try first to parse the allOf, oneOf and allOf and only then the DataType?

This would be a bit of an assumption though that the composite keywords (oneOf, anyOf, allOf) have priority over the object type. I opened a ticket in the springdoc repo which causes such a yaml to be generated: springdoc/springdoc-openapi#1589

if let dataType = DataType(jsonDictionary: jsonDictionary) {
switch dataType {
case .array:
self = .array(try ArraySchema(jsonDictionary: jsonDictionary))
case .object:
self = .object(try ObjectSchema(jsonDictionary: jsonDictionary))
case .string:
self = .string(StringSchema(jsonDictionary: jsonDictionary))
case .number:
self = .number(NumberSchema(jsonDictionary: jsonDictionary))
case .integer:
self = .integer(IntegerSchema(jsonDictionary: jsonDictionary))
case .boolean:
self = .boolean
}
} else if jsonDictionary["$ref"] != nil {

closed by PR