OpenAPITools / OpenAPITools/openapi-generator
[REQ] New global flag for identical API method interfaces no matter if formdata or not
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
Is your feature request related to a problem? Please describe.
Currently in all generators a different interface is created for API methods depending on content-type.
Requests using formdata (multipart/form-data and application/x-www-form-urlencoded) will list all request properties in the API method signature. Anything else (application/json) will require the properties to be included as part of a model instance.
This is not ideal as any given endpoint have support for both multipart/form-data and application/json. Any endpoints that share the base object ref but have different content-types would also have vastly different API interfaces.
For the addPet example:
paths:
/pet:
post:
tags:
- pet
summary: Add a new pet to the store
description: ''
operationId: addPet
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
'405':
description: Invalid input
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
when content-type is application/json the following interface is generated in Java (and all generators):
public okhttp3.Call addPetCall(Pet pet, final ApiCallback _callback) throws ApiException {
and for multipart/form-data:
public okhttp3.Call addPetCall(String name, List<String> photoUrls, Long id, Category category, List<Tag> tags, String status, final ApiCallback _callback) throws ApiException {
The data sent to the API endpoint is identical, but the interfaces are not compatible with each other.
Describe the solution you'd like
A simple way to get around this is to nest the formdata request in a property:
paths:
/pet:
post:
tags:
- pet
summary: Add a new pet to the store
description: ''
operationId: addPet
responses:
'200':
description: successful operation
content:
application/xml:
schema:
$ref: '#/components/schemas/Pet'
application/json:
schema:
$ref: '#/components/schemas/Pet'
'405':
description: Invalid input
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
pet:
$ref: '#/components/schemas/Pet'
required: true
The generated interface is now identical as when application/json:
public okhttp3.Call addPetCall(Pet pet, final ApiCallback _callback) throws ApiException {
However, the obvious problem here is that data will be sent to the API endpoint nested within a pet key, not at root-level as you would expect.
Expected, root-level:
name="some name"
photoUrls[0]="some_url"
id=123
category[id]=123
category[name]="Category_Name"
tags[0][id]=123
tags[0][name]="tag_1"
status="pending"
What instead happens:
pet[name]="some name"
pet[photoUrls][0]="some_url"
pet[id]=123
pet[category][id]=123
pet[category][name]="Category_Name"
pet[tags][0][id]=123
pet[tags][0][name]="tag_1"
pet[status]="pending"
My proposal includes a new extension similar to x-codegen-request-body-name. This new extension can be used to define the property name to use (assuming the name is not automatically calculated by openapi-generator) or as a boolean flag to enable the new functionality.
New functionality being, when the extension is detected and request contains formdata, to move all data within {propertyName} into the root-level, to behave as current behavior.
All generators would need to be updated to support this new extension.
Describe alternatives you've considered
Instead of having to update the openapi schema, maybe the extension could be used to instead create the same interfaces regardless of content-type.
In other words, end-user would not be required to do
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
pet:
$ref: '#/components/schemas/Pet'
and could simply keep it as
requestBody:
content:
multipart/form-data:
schema:
$ref: '#/components/schemas/Pet'
where only the content-type changes but the generator outputs identical code.
Additional context
This proposal deals only with debating the merits of the idea, the extension name and type (string/boolean flag) and maybe updating a select few generators as initial candidates.
I am not proposing updating all generators at once to add this support.
This new feature may be incompatible to other existing flags like Java's useSingleRequestParameter flag. However, that flag appears to nest all data into a single object, including parameters in path/query/header/cookies.
My proposal focuses solely on creating a unified interface for all API methods regardless of content-type chosen for the endpoint.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing how requestBody content types and the existing x-codegen-request-body-name extension are handled in the generators, using the Java addPet examples as a reference. Compare the generated interfaces and form-data payload shapes, then define the extension behavior and select initial generators before implementation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100