yonaskolb/SwagGen

Partial update with nil value when using PATCH api

marcuswu0814 opened this issue · 3 comments

Hi everyone:

In example spec Rocket, api UpdateProfileWithId using PATCH to partial update value.

But if in some cases we need to update ProfileUpdateRequest’s name be empty value, is it possible to adjust spec file to align the requirement?

Its a bit tricky to represent this in Swift (see a related question here: https://forums.swift.org/t/partial-encoding-for-patch-updates/13428) since OpenAPI has two concepts to consider:

  1. Presence - If a key exists in a JSON object
  2. Nullability - If the value is null or not

In Swift, we have just Optional<T> to represent both of these states on our model types and unfortunately we have to decide to either treat Optional.none/nil as either null (by using encode(_:forKey:)) or to emit it entirely (by using encodeIfPresent(_:forKey:)) at the point of encoding.

Its a frustrating limitation of Swift's Codable implementation and i've not yet come across a great way of handling it. Do you have a suggestion on how you'd see it working in SwagGen? I'm curious because I'm also looking for a solution 😄

Hi @yonaskolb, @liamnichols:

I have an idea for this and need next step instructions.

Please take a look my gist SwagGen NullCodable Proposal · GitHub.

In case, client knew when should encode the null, use NullCodable property wrapper to mark optional value and use it prjoectedValue to give a encodingOption, just like my example.

It work for me and need some discussion on this proposal, I can make a PR for this, but need some check: Add an additional command option for generate different version? Or given a default behavior like before? (I think this is not a breaking change)

If some good suggestion, please feel free to tell me. 🙏

I created a PR for this situation, please take a look. 🙏

Maybe we shouldn't need to update any core of SwagGen but IMO build in this feature is good for some cases like use PATCH HTTP method.

example:

class SomeGenModel {

  @NullCodable
  var optionalValue: String?


  // ...
}

var myGenModel = SomeGenModel()
myGenModel.$optionalValue.encodingOption = .encodeNull