Skip to content

Having issues with propertyName: type when using swift-openapi-generator #542

Description

@nezhyborets

There are 58 schemas that use discriminator. 56 of them define propertyName: type, so let's focus on them. Let's consider a simple schema from the spec that has this:

FunctionAndCustomToolCallOutput:
  oneOf:
    - $ref: '#/components/schemas/InputTextContent'
    - $ref: '#/components/schemas/InputImageContent'
    - $ref: '#/components/schemas/InputFileContent'
  discriminator:
    propertyName: type

What swift-openapi-generator makes from this is the following:

/// - Remark: Generated from `#/components/schemas/FunctionAndCustomToolCallOutput`.
@frozen public enum FunctionAndCustomToolCallOutput: Codable, Hashable, Sendable {
    /// - Remark: Generated from `#/components/schemas/FunctionAndCustomToolCallOutput/InputTextContent`.
    case inputTextContent(Components.Schemas.InputTextContent)
    /// - Remark: Generated from `#/components/schemas/FunctionAndCustomToolCallOutput/InputImageContent`.
    case inputImageContent(Components.Schemas.InputImageContent)
    /// - Remark: Generated from `#/components/schemas/FunctionAndCustomToolCallOutput/InputFileContent`.
    case inputFileContent(Components.Schemas.InputFileContent)
    public enum CodingKeys: String, CodingKey {
        case _type = "type"
    }
    public init(from decoder: any Swift.Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let discriminator = try container.decode(
            Swift.String.self,
            forKey: ._type
        )
        switch discriminator {
        case "InputTextContent", "#/components/schemas/InputTextContent":
            self = .inputTextContent(try .init(from: decoder))
        case "InputImageContent", "#/components/schemas/InputImageContent":
            self = .inputImageContent(try .init(from: decoder))
        case "InputFileContent", "#/components/schemas/InputFileContent":
            self = .inputFileContent(try .init(from: decoder))
        default:
            throw Swift.DecodingError.unknownOneOfDiscriminator(
                discriminatorKey: CodingKeys._type,
                discriminatorValue: discriminator,
                codingPath: decoder.codingPath
            )
        }
    }
    public func encode(to encoder: any Swift.Encoder) throws {
        switch self {
        case let .inputTextContent(value):
            try value.encode(to: encoder)
        case let .inputImageContent(value):
            try value.encode(to: encoder)
        case let .inputFileContent(value):
            try value.encode(to: encoder)
        }
    }
}

As we see inside switch discriminator, it uses either schema name (i.e. InputTextContent) or the reference (i.e #/components/schemas/InputTextContent) in order to understand the case to make self. On one hand we could say that it's a bug that the generator didn't use type property of, for example, InputTextContent (input_text). But on the other had, here on swagger.io, under Mapping Type Names they say:

It is implied, that the property to which discriminator refers, contains the name of the target schema. In the example above, the objectType property should contain either simpleObject, or complexObject string.

And also important

If the property values do not match the schema names, you can map the values to the names.
So, in our case, it is implied that type field in InputTextContent should contain InputTextContent, but instead it contains input_text.

So my question is, what would be the correct fix for this? Fix the generator, or make corresponding mappings in the spec?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingquestionFurther information is requestedreproReproduced; investigation details recorded in LinearspecificationOpenAPI contract, authored schema, or specification publication defects.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions