Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • O openapi-generator
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 3,476
    • Issues 3,476
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 402
    • Merge requests 402
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • OpenAPI Tools
  • openapi-generator
  • Issues
  • #10926
Closed
Open
Issue created Nov 22, 2021 by Administrator@rootContributor

[Swift5] Generate models where optional properties (`x-swift-always-encode`) can be flagged to explicitly encode nil when empty

Created by: jarrodparkes

Description

For certain API's, you must explicitly set optional properties to "null" to achieve a desired outcome.

For example, consider an API with the endpoint PATCH /appointment/{appointment_id} where the request body can be used to set an appointment's start time to "null" — this might transition the appointment to a "reschedule" state:

{
  "start_time": null
}

As of openapi-generator@5.3.1, optional properties are only encoded if a value is present (encodeIfPresent). For example:

public struct AppointmentPatchPayload: Codable {

    public private(set) var startAt: Date?

    public init(startAt: Date? = nil) {
        self.startAt = startAt
    }

    public enum CodingKeys: String, CodingKey, CaseIterable {
        case startAt = "start_at"
    }

    // Encodable protocol methods

    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encodeIfPresent(startAt, forKey: .startAt)
    }
}

This issue is a request to modify the swift5 generator so that optional properties can be flagged to explicitly encode nil when empty.

openapi-generator version

openapi-generator@5.3.1; not a regression

OpenAPI declaration file content or url

{
  "title": "AppointmentPatchPayload",
  "type": "object",
  "description": "Payload for patching an appointment.",
  "properties": {
    "start_at": {
      "type": "string",
      "description": "The new date and time (ISO 8601 format) when the appointment is set to start.",
      "format": "date-time"
    }
}

Command line used for generation

docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli:v5.3.1 generate \
    -I /local/spec/out/Aryeo/Aryeo.MERGED.json \
    -g swift5 \
    --additional-properties readonlyProperties=true,hashableModels=false \
    --skip-validate-spec \
    -o /local/sdk

Steps to reproduce

  1. Create a spec containing a model (ex: AppointmentPatchPayload) with an optional/nullable property
  2. Run the swift5 generator
  3. Observe the model

Related issues/PRs

  • (swift4, nil/unwrap behavior) https://github.com/OpenAPITools/openapi-generator/pull/1527
  • (add new extension) https://github.com/OpenAPITools/openapi-generator/issues/1916
  • (extensions not being loaded) https://github.com/OpenAPITools/openapi-generator/issues/10133

Suggest a fix/enhancement

Support an OAS extension such as x-swift-always-encode to inform the swift5 generator to always encode a value for optional properties. The resulting model might look like this:

public struct AppointmentPatchPayload: Codable {

    public private(set) var startAt: Date?

    public init(startAt: Date? = nil) {
        self.startAt = startAt
    }

    public enum CodingKeys: String, CodingKey, CaseIterable {
        case startAt = "start_at"
    }

    // Encodable protocol methods

    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)

        if let startAt = startAt {
            try container.encode(startAt, forKey: .startAt)
        } else {
            try container.encodeNil(forKey: .startAt)
        }
    }
}
Assignee
Assign to
Time tracking