[swift5/swift6] Fix oneOf decoding when enumUnknownDefaultCase is enabled#23496
[swift5/swift6] Fix oneOf decoding when enumUnknownDefaultCase is enabled#23496jasperpatterson wants to merge 3 commits intoOpenAPITools:masterfrom
Conversation
There was a problem hiding this comment.
4 issues found across 23 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="modules/openapi-generator/src/main/resources/swift6/model.mustache">
<violation number="1" location="modules/openapi-generator/src/main/resources/swift6/model.mustache:35">
P2: Unknown-case detection skips enums inside containers, so oneOf decoding can still accept a variant even when enum elements fell back to `.unknownDefaultOpenApi`.</violation>
</file>
<file name="modules/openapi-generator/src/main/resources/swift5/model.mustache">
<violation number="1" location="modules/openapi-generator/src/main/resources/swift5/model.mustache:39">
P2: containsUnknownDefaultOpenApiCase skips enum containers, so unknown enum values inside arrays/maps are not detected and oneOf decoding can still accept the wrong variant.</violation>
</file>
<file name="samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Models/EnumArrays.swift">
<violation number="1" location="samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Models/EnumArrays.swift:47">
P2: UnknownCaseCheckable ignores arrayEnum, so unknown enum values in array_enum won’t be detected and oneOf discrimination can accept a variant based on unknown-enum fallback.</violation>
</file>
<file name="samples/client/petstore/swift5/resultLibrary/PetstoreClient/Classes/OpenAPIs/Models/EnumArrays.swift">
<violation number="1" location="samples/client/petstore/swift5/resultLibrary/PetstoreClient/Classes/OpenAPIs/Models/EnumArrays.swift:50">
P2: UnknownCaseCheckable ignores arrayEnum, so unknown enum defaults inside arrayEnum are not detected.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| {{#allVars}} | ||
| {{#isEnum}} | ||
| {{^isContainer}} | ||
| {{#vendorExtensions.x-null-encodable}} |
There was a problem hiding this comment.
P2: Unknown-case detection skips enums inside containers, so oneOf decoding can still accept a variant even when enum elements fell back to .unknownDefaultOpenApi.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/swift6/model.mustache, line 35:
<comment>Unknown-case detection skips enums inside containers, so oneOf decoding can still accept a variant even when enum elements fell back to `.unknownDefaultOpenApi`.</comment>
<file context>
@@ -26,4 +26,40 @@ extension {{projectName}}API {
+ {{#allVars}}
+ {{#isEnum}}
+ {{^isContainer}}
+ {{#vendorExtensions.x-null-encodable}}
+ if {{{name}}} == .encodeValue(.unknownDefaultOpenApi) { return true }
+ {{/vendorExtensions.x-null-encodable}}
</file context>
| {{#allVars}} | ||
| {{#isEnum}} | ||
| {{^isContainer}} | ||
| {{#vendorExtensions.x-null-encodable}} |
There was a problem hiding this comment.
P2: containsUnknownDefaultOpenApiCase skips enum containers, so unknown enum values inside arrays/maps are not detected and oneOf decoding can still accept the wrong variant.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/swift5/model.mustache, line 39:
<comment>containsUnknownDefaultOpenApiCase skips enum containers, so unknown enum values inside arrays/maps are not detected and oneOf decoding can still accept the wrong variant.</comment>
<file context>
@@ -30,4 +30,40 @@ extension {{projectName}}API {
+ {{#allVars}}
+ {{#isEnum}}
+ {{^isContainer}}
+ {{#vendorExtensions.x-null-encodable}}
+ if {{{name}}} == .encodeValue(.unknownDefaultOpenApi) { return true }
+ {{/vendorExtensions.x-null-encodable}}
</file context>
|
|
||
| extension EnumArrays: UnknownCaseCheckable { | ||
| internal var containsUnknownDefaultOpenApiCase: Bool { | ||
| if justSymbol == .unknownDefaultOpenApi { return true } |
There was a problem hiding this comment.
P2: UnknownCaseCheckable ignores arrayEnum, so unknown enum values in array_enum won’t be detected and oneOf discrimination can accept a variant based on unknown-enum fallback.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Models/EnumArrays.swift, line 47:
<comment>UnknownCaseCheckable ignores arrayEnum, so unknown enum values in array_enum won’t be detected and oneOf discrimination can accept a variant based on unknown-enum fallback.</comment>
<file context>
@@ -41,3 +41,10 @@ internal struct EnumArrays: Sendable, Codable {
+
+extension EnumArrays: UnknownCaseCheckable {
+ internal var containsUnknownDefaultOpenApiCase: Bool {
+ if justSymbol == .unknownDefaultOpenApi { return true }
+ return false
+ }
</file context>
| if justSymbol == .unknownDefaultOpenApi { return true } | ||
| return false | ||
| } |
There was a problem hiding this comment.
P2: UnknownCaseCheckable ignores arrayEnum, so unknown enum defaults inside arrayEnum are not detected.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/swift5/resultLibrary/PetstoreClient/Classes/OpenAPIs/Models/EnumArrays.swift, line 50:
<comment>UnknownCaseCheckable ignores arrayEnum, so unknown enum defaults inside arrayEnum are not detected.</comment>
<file context>
@@ -44,3 +44,10 @@ internal struct EnumArrays: Codable, JSONEncodable {
+
+extension EnumArrays: UnknownCaseCheckable {
+ internal var containsUnknownDefaultOpenApiCase: Bool {
+ if justSymbol == .unknownDefaultOpenApi { return true }
+ return false
+ }
</file context>
| if justSymbol == .unknownDefaultOpenApi { return true } | |
| return false | |
| } | |
| if justSymbol == .unknownDefaultOpenApi { return true } | |
| if arrayEnum?.contains(.unknownDefaultOpenApi) == true { return true } | |
| return false |
When
enumUnknownDefaultCase=trueis used withoneOftypes, the generated Swift decoding logic always matches the first variant and never tries subsequent ones, effectively breakingoneOfdiscrimination.Root Cause
Two features interact badly:
enumUnknownDefaultCase=trueaddsCaseIterableDefaultsLastconformance to every generated enum, making enum decoding never throw — unknown values silently fall back to.unknownDefaultOpenApi.oneOfdecoder usestry? container.decode(Variant.self)to attempt each variant in order. Since inner enum properties never fail to decode, the first variant always succeeds.Fix
Introduces an
UnknownCaseCheckableprotocol that lets theoneOfdecoder reject a variant whose enum properties only matched due to the unknown-case fallback:Models.mustache— Defines theUnknownCaseCheckableprotocol with a default implementation returningfalse(only whenenumUnknownDefaultCaseis enabled)model.mustache— Generates conformance extensions only on types that have enum properties ({{#hasEnums}}):modelOneOf.mustache— Adds a guard to the non-discriminator decode path:PR checklist
Commit all changed files.
This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
These must match the expectations made by your contribution.
You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example
./bin/generate-samples.sh bin/configs/java*.IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
master(upcoming7.x.0minor release - breaking changes with fallbacks),8.0.x(breaking changes without fallbacks)"fixes #123"present in the PR description)Summary by cubic
Fixes Swift
oneOfdecoding whenenumUnknownDefaultCase=trueby skipping variants that only decode due to.unknownDefaultOpenApifallbacks. This restores correct variant detection foroneOfwithout discriminators in Swift 5 and 6.UnknownCaseCheckableprotocol with a defaultfalseimplementation (Swift5/Swift6Models.mustache).UnknownCaseCheckableconformance only for types/enums with enum properties; skip arrays, maps, andoneOfinterfaces.oneOfdecoding to reject values wherecontainsUnknownDefaultOpenApiCase == true(Swift5/Swift6modelOneOf.mustache).enumUnknownDefaultCaseis disabled.Written for commit 97c5c3b. Summary will update on new commits.