Skip to content

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

Description

@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

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)
        }
    }
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions