Closed atacan closed 3 weeks ago
I expect this OpenAPI document might be missing a discriminator for the anyOf
. Without that, there might not be much we can do.
Thank you. I checked it, and it uses oneOf
.
EDIT:
Changing it to anyOf
didn't work either.
I also moved the CreateTranscriptionResponseVerboseJson
one line up to be before the other one. It still decodes the response as CreateTranscriptionResponseJson
/audio/transcriptions:
post:
operationId: createTranscription
tags:
- Audio
summary: Transcribes audio into the input language.
requestBody:
required: true
content:
multipart/form-data:
schema:
$ref: "#/components/schemas/CreateTranscriptionRequest"
responses:
"200":
description: OK
content:
application/json:
schema:
- oneOf:
+ anyOf:
- - $ref: "#/components/schemas/CreateTranscriptionResponseJson"
- $ref: "#/components/schemas/CreateTranscriptionResponseVerboseJson"
+ - $ref: "#/components/schemas/CreateTranscriptionResponseJson"
OK. I found the problem. A numeric property is specified as a string.
Putting the expected value before is still important, because in case of anyOf
decode tries one by one, and if one type is a subset of the other the decoder will work.
public init(from decoder: any Decoder) throws {
var errors: [any Error] = []
do {
value1 = try .init(from: decoder)
} catch {
errors.append(error)
}
do {
value2 = try .init(from: decoder)
} catch {
errors.append(error)
}
try Swift.DecodingError.verifyAtLeastOneSchemaIsNotNil(
[
value1,
value2
],
type: Self.self,
codingPath: decoder.codingPath,
errors: errors
)
}
same goes for oneOf
The important difference is that the payload must match exactly one schema in a oneOf, and one or more in an allOf. If one is a subset of the other, then by definition it cannot be oneOf (as it can match both), and would be an anyOf.
The discriminator wouldn't make a difference here, because when parsing an anyOf, all the schemas are given a chance to decode the payload and the order doesn't change the result.
Question
I have the following generated struct s. Even though the server returns the
CreateTranscriptionResponseVerboseJson
(I see it in proxyman), the response is parsed asCreateTranscriptionResponseJson
. I guess because it is a subset of the verbose one and it's the one that's first tried?Full reproduction: https://github.com/atacan/swift-openai-api/blob/c087e61ed66ea40e627b785e8146bddd44a5e8b8/Tests/OpenAIAsyncHTTPClientTests/OpenAIAsyncHTTPClientTest.swift#L90
Code snippets are below
the code