Skip to content

Fix: Optional url parameter encoding#77

Open
matejmolnar wants to merge 5 commits intodevfrom
mm/fix/optional-url-parameter-encoding
Open

Fix: Optional url parameter encoding#77
matejmolnar wants to merge 5 commits intodevfrom
mm/fix/optional-url-parameter-encoding

Conversation

@matejmolnar
Copy link
Collaborator

Objective of this PR

Solve an issue which broke url parameter encoding in a pretty sneaky manner.

Example

Let's say you have a router like so

private enum ExampleRouter: Requestable {
    case items(limit: Int?)

    var urlParameters: [String: Any]? {
        switch self {
        case let .items(limit):
            [
                "limit": limit
            ]
        }
    }

Looks good, but when we run it we find out that the resulting parameter would get encoded as limit=Optional(10) instead of limit=10.
Now you might say okay let's fix it by mapping the dictionary values to non optionals like so:

            [
                "limit": limit
            ].compactMapValues { $0 }

Nice! Everything works now.

After some time there's a new requirement to add another parameter of type String to the request like so:

private enum ExampleRouter: Requestable {
    case items(limit: Int?, filter: String?)

    var urlParameters: [String: Any]? {
        switch self {
        case let .items(limit, filter):
            [
                "limit": limit,
                "filter": filter
            ].compactMapValues { $0 }
        }
    }

Everything should work right?

Wrong! The resulting parameters are once again being encoded as limit=Optional(10)&filter=Optional(test).
What changed?!

Before the dictionary got resolved as [String: Int?] by the compiler before applying the compactMapValues, however now we have multiples types in the dictionary hence it gets resolved as [String: Any] so the compactMapValues doesn't do anything.

Solution

During encoding unwrap the Any type in case it's optional by using mirroring.

@matejmolnar matejmolnar changed the base branch from master to dev January 14, 2026 10:03
gajddo00
gajddo00 previously approved these changes Jan 14, 2026
Copy link
Contributor

@gajddo00 gajddo00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦑

@matejmolnar matejmolnar requested review from a team and cejanen January 14, 2026 10:46
TParizek
TParizek previously approved these changes Jan 16, 2026
Copy link

@TParizek TParizek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thanks for fixing the bug!

I see that tests are failing on CI with iOS 18 runtime. Would you mind please bumping test target iOS to iOS 26 to resolve the issue?

cejanen
cejanen previously approved these changes Jan 16, 2026
Copy link
Contributor

@cejanen cejanen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚁

I would like to see running CI, currently we fix it on all projects

@matejmolnar matejmolnar dismissed stale reviews from cejanen, TParizek, and gajddo00 via e117064 January 16, 2026 10:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants