Closed jakepetroules closed 4 months ago
Thanks @jakepetroules, let us take a look at this. The combination of multipart and typed additional properties might not be something I've seen before. But I do think your OpenAPI inputs are valid, so we should make this work.
The inclusion of JobParameters2 is merely for illustration. That's what I would have expected JobParameters to look like.
Multipart has special handling in Swift OpenAPI Generator. The schema is generated differently because it's used as the top level object that describes the possible multipart parts. More on that in the original proposal: https://swiftpackageindex.com/apple/swift-openapi-generator/1.2.1/documentation/swift-openapi-generator/soar-0009#Different-enum-case-types
So JobParameters and JobParameters2 will not look the same, and both are generated correctly.
The issue I'm now looking into is why the code doesn't compile, that's the only problem I see right now.
It was initially quite unclear to me how to pass a [String: String] into this construct, as I would have expected something like this at the call site:
body: .multipartForm(.init(additionalProperties: parameters)) but you actually need to use this:
body: .multipartForm(.init(parameters.map { .additionalProperties(.init(payload: $0.value, name: $0.key)) }))
Yes, this is also expected. The top level object
of a multipart schema is used as the blueprint that lists the various multipart parts that are recognized. More docs on that:
Yikes, so this has at least one bug: the proposal dictates the additional properties enum case to be called "other", but it's only called that in some cases, but "additionalProperties" in other. That's my oversight, and I'll think about how to fix this without breaking backwards compatibility. That's issue 1. Still digging into issue 2, as reported by Jake.
Ok issue 2 is a genuine bug in the mapping of type: string
to the Swift type. Should not be Swift.String
, as in raw bodies (which multipart parts are a type of), we represent raw strings as a streaming HTTPBody
instead.
So once fixed, the underlying type will go from:
@frozen public enum JobParameters: Sendable, Hashable {
case additionalProperties(OpenAPIRuntime.MultipartDynamicallyNamedPart<Swift.String>)
}
to
@frozen public enum JobParameters: Sendable, Hashable {
case additionalProperties(OpenAPIRuntime.MultipartDynamicallyNamedPart<OpenAPIRuntime.HTTPBody>)
}
A reminder that you can easily go from HTTPBody to a String using https://swiftpackageindex.com/apple/swift-openapi-runtime/1.4.0/documentation/openapiruntime/swift/string/init(collecting:upto:)
And since this never compiled, I think it should be okay to do this "breaking change"? WDYT, @simonjbeaumont?
@jakepetroules A fix incoming here: https://github.com/apple/swift-openapi-generator/pull/597
The other issue (other
vs additionalProperties
) is not a blocker, and we'll fix that separately: https://github.com/apple/swift-openapi-generator/issues/598
@jakepetroules Ok fixed in 1.3.0: https://github.com/apple/swift-openapi-generator/releases/tag/1.3.0
Description
OpenAPI allows using the following construct to represent a
[String: String]
dictionary:However, this doesn't work correctly with multipart/form-data
Reproduction
Considering the following code...
Schema request body:
Schema components:
This generated the following Swift code:
Package version(s)
swift-openapi-generator 1.2.1 swift-openapi-runtime 1.4.0
Expected behavior
The inclusion of JobParameters2 is merely for illustration. That's what I would have expected JobParameters to look like.
It was initially quite unclear to me how to pass a
[String: String]
into this construct, as I would have expected something like this at the call site:but you actually need to use this:
However, the final problem is this:
The generated code doesn't compile, as
value
is aString
, but anHTTPBody
is expected there.I was able to work around the compile error by adding to my target:
That seems to work at runtime as well.
Environment
N/A
Additional information
No response