Skip to content

Conversation

jakubno
Copy link

@jakubno jakubno commented Aug 7, 2025

Description

Adds support for OpenAPI array parameters, especially regarding the explode and style attributes, and enhances validation and code generation for parameters in the generated client.

The most significant changes include updating the OpenAPI schema models for parameters, propagating the explode attribute through the parsing logic, and updating generated code and tests to handle non-exploded array parameters.

References:

richardlarocque added a commit to getoutreach/openapi-python-client that referenced this pull request Sep 17, 2025
Updates the data models to capture `style` and `explode` parameters.
There was a PR outstanding that went in this direction [1].  We might
want to rebase on top of that one day, when it's merged.  For now we
settle for some more targeted changes.

Updates "ModelProperty" and related templates with a `to_deep_dict()`
serialization option.  This option differs from the regular `to_dict()`
in that nested dicts are flattened.  It also adds a `[]` suffix for keys
that point at arrays.  Finally, it takes a "prefix" argument that is the
base name of this object.

The end result of all this is that we can have a deepObject query param
named `filter` that results in some `FooFilter` model param.  We can
initialize it as
```python
FooFilter.from_dict({'owner': { 'id': [12, 34] }})
```
then invoke its `to_deep_dict()` method to get
```python
{ 'filter[owner][id][]': [12, 34] }
```
which, when passed in to `httpx`, will result in a query param like
```
?filter[owner][id][]=12&filter[owner][id][]=34
```
which is exactly the format that APIv2 expects.  This is not a
coincidence.  We're doing this specifically to support APIv2.

Unfortunately, I don't see a straightforward way to polish and upstream
this change.  The serialization conventions above are "Rails-style" [2],
one of many possible interpretations of how an OpenAPI deepObject should
act.  The spec doesn't actually specify very much here.

So, while this is technically not *against* the spec, this is probably
not the interpretation that a Python generator would go with by default.
(Maybe one day it could be configurable?  Or just wait and see if
OpenAPI delivers on its promise to fix all this?)

I feel like "fork" is the best option for us for now.

Since I don't expect this to be upstreamed, I haven't put much effort
into updating test suites.  I expect that would only make later rebases
more difficult, without actually testing what we want most, which is
"do the generated libraries work with our API?"

[1] openapi-generators#1296
[2] OAI/OpenAPI-Specification#1706 (comment)
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.

1 participant