apple / apple/swift-openapi-generator

Surface the distinction between an explicit "null" value and an absent value

Open
#419 38 comments 1 reaction 0 assignees View on GitHub
area/generator area/runtime kind/enhancement
Dominant language
Swift
Stars
2k
Forks
182
Avg merge
13h 28m
Merged PRs (30d)
5

Description

When using a schema that has a field from a reference that is both non-required and "nullable" this is a common way of defining it in OpenAPI: 3.1.0
```yaml
UpdateTaskOccurrenceCompletionResponse:
properties:
old_task:
$ref: '#/components/schemas/TaskOccurenceDTO'
next_task:
oneOf:
- $ref: '#/components/schemas/TaskOccurenceDTO'
- type: 'null'
type: object
required:
- old_task
```
but this currently generates the following API:
```swift
/// - Remark: Generated from `#/components/schemas/UpdateTaskOccurrenceCompletionResponse`.
public struct UpdateTaskOccurrenceCompletionResponse: Codable, Hashable, Sendable {
/// - Remark: Generated from `#/components/schemas/UpdateTaskOccurrenceCompletionResponse/old_task`.
public var old_task: Components.Schemas.TaskOccurenceDTO
/// - Remark: Generated from `#/components/schemas/UpdateTaskOccurrenceCompletionResponse/next_task`.
@frozen public enum next_taskPayload: Codable, Hashable, Sendable {
/// - Remark: Generated from `#/components/schemas/UpdateTaskOccurrenceCompletionResponse/next_task/case1`.
case TaskOccurenceDTO(Components.Schemas.TaskOccurenceDTO)
/// - Remark: Generated from `#/components/schemas/UpdateTaskOccurrenceCompletionResponse/next_task/case2`.
case case2(OpenAPIRuntime.OpenAPIValueContainer)
}
/// - Remark: Generated from `#/components/schemas/UpdateTaskOccurrenceCompletionResponse/next_task`.
public var next_task: Components.Schemas.UpdateTaskOccurrenceCompletionResponse.next_taskPayload
```
This is quite confusing syntax at the callsite, since we have this weird `case2`, instead of just having only an optional `TaskOccurenceDTO`. Is this expected behaviour or could we do something to improve the ergonomics before the 1.0.0 release? I'll happily work on a PR, if you could point me in the right direction to where in the codebase the relevant parts are!

Contributor guide

Open the contributing guide

Research direction

Use the OpenAPI 3.1 schema and generated UpdateTaskOccurrenceCompletionResponse shown in the report as the reproduction. Trace how the optional nullable next_task field becomes next_taskPayload, then determine a representation that distinguishes an absent value from an explicit null without the confusing case2 API. Done means the generated Swift API has clearer call-site ergonomics and preserves both states.

Written by the indexing model from the issue text.

Assessment

Tech stack
openapi, swift
Domain
api, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.