Description
Hello,
I was wondering if OpenAPI or the OpenAPI generator could define new scalar types.
New scalar types help disambiguating scalar values such as integers or strings by making them strongly typed: this is a user id, this is an ISO-8601 date, this is a number of seconds, this is an amount of cents. With strong typing, mixing apples and oranges is impossible.
OpenAPI has something that looks pretty much like this:
components:
schemas:
# A custom string scalar:
URL:
type: string
PhoneNumber:
type: object
properties:
localized_description:
type: string
# Not a string, but a URL:
url:
$ref: '#/components/schemas/URL'
required:
- localized_description
- url
But OpenAPI Generator imports them as their raw Swift type. For example:
// Generated
public enum Components {
public enum Schemas {
/// - Remark: Generated from `#/components/schemas/URL`.
public typealias URL = Swift.String
}
}
Somehow I was expecting Components.Schemas.URL
to be generated as a RawRepresentable
type, as below. I thought that the definition of #/components/schemas/URL
was a sufficient hint for the desire of a custom type:
// My expectation
public enum Components {
public enum Schemas {
/// - Remark: Generated from `#/components/schemas/URL`.
public struct URL: Codable, Hashable, Sendable, RawRepresentable {
public var rawValue: String
public init(rawValue: String) {
self.rawValue = rawValue
}
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
try self.init(rawValue: container.decode(String.self))
}
public func encode(to encoder: any Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(rawValue)
}
}
}
}
I understand that OpenAPI supports a lot of features, such as string formats, that can turn a simple feature into a very complex beast.
I also understand that not everybody has a real or strong need for strongly-types scalars. They could annoy some users ("All those raw values 🙄").
My previous experience with strongly-types scalars was the Swift GraphQL library Apollo: Custom Scalars. By default, it imports custom scalars as their raw Swift representation (so the URL
above with also be a typealias to Swift.String
). But it allows the developer to provide a custom implementation. I was able to replace all those raw String
and Int
with tagged values, with much happiness.
In the end, I wonder what is the opinion of the library maintainers on such a topic?