-
-
Notifications
You must be signed in to change notification settings - Fork 6.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[java] [typescript-angular] Regression: No model for array of type file #1458
Comments
Hi, |
@Clovisforyou : What's exactly your error / issue? The unknown model? Did you try changing the signature of the .json for the api? "/be/files/staged": {
"post": {
"tags": [
"atrs-backend-file-upload-controller"
],
"summary": "uploadFilesToStage",
"operationId": "uploadFilesToStageUsingPOST",
"consumes": [
"multipart/form-data"
],
"produces": [
"*/*"
],
"parameters": [
{
"name": "uploadId",
"in": "query",
"description": "uploadId",
"required": true,
"type": "string"
},
{
"name": "files",
"in": "formData",
"description": "files",
"required": true,
"type": "array",
"items": {
"type": "file"
},
"collectionFormat": "multi"
}
],
"responses": {
"200": { "description": "OK", "schema": { "$ref": "#/definitions/StagedFileUploadStatus" }},
"201": {"description": "Created"},
"401": {"description": "Unauthorized" },
"403": { "description": "Forbidden" },
"404": { "description": "Not Found" } }
}
}, To achieve that, the spring boot code had to be changed from Array ([]) to List, as follows: @RequestMapping(value = "/staged", method = RequestMethod.POST,consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public StagedFileUploadStatus uploadFilesToStage(@RequestParam String uploadId, @RequestParam List<MultipartFile> files) throws IOException { The code is actually generated. However, in the Java code / mustache template, it appears that the incorrect code branch is selected. This generates the following: if (files) {
formParams = formParams.append('files', files.join(COLLECTION_FORMATS['csv'])) || formParams;
} Looking at the mustache, this should be generated if the collection format is not multi. In the json it's {{#isCollectionFormatMulti}}
{{paramName}}.forEach((element) => {
{{#useHttpClient}}formParams = {{/useHttpClient}}formParams.append('{{baseName}}', <any>element){{#useHttpClient}} || formParams{{/useHttpClient}};
})
{{/isCollectionFormatMulti}}
{{^isCollectionFormatMulti}}
{{#useHttpClient}}formParams = {{/useHttpClient}}formParams.append('{{baseName}}', {{paramName}}.join(COLLECTION_FORMATS['{{collectionFormat}}'])){{#useHttpClient}} || formParams{{/useHttpClient}};
{{/isCollectionFormatMulti}} So I'm not sure, why the collectionFormat is not multi here and the lower branch of the mustache is selected. |
I test you json and I have the same issue.
I will try to investigate more about this. |
@akehir Well very strange, with content declared in line I didnt get an error and all work correctly. You are using 2.0 or 3.0 ?
|
The problems that I have detected with this are:
|
I'm using swagger / openapi 2.0: {
"swagger": "2.0",
} But in both our cases, the generator goes into the |
@akehir I agree that this is a bug, and should be fixed. Do you have time to implement a fix? |
@macjohnny : If it was just updating the generated client code I'd have made a PR. The problem is, that I suspect that an incorrect condition is set in the codegen .jar itself. Below, you see the relevant template code. Generated is what's in
Furthermore is also that currently the generated API's have While I can fix and test a generated angular client well enough, I'm not sure I can provide a fix for the java code itself (or that I'd know if indeed an incorrect code branch is selected). Furthermore, the petstore API itself does not cover these 2 cases, so there are no existing tests where we could confirm the regression is fixed correctly. It might be sensible to add a new api call with an array of files as well - Although probably most client's don't even test the normal file upload api's. The angular client for sure doesn't test the normal file upload. See #1458 (comment) for more detail |
Ok, I took a quick glance at the relevant code. There are 2 relevant code parts: in 1, the code calls 2, and if I assume the default generator needs to handle both version 2 and version 3 of OpenAPI, and then not return null, which would prevent the default fallback to .csv. The fallback to csv is furthermore only sensible, if explode is set to false (which is not the default for a form, but in all other cases), so a default fallback to 'multi' might be better as well - at the very least in OpenAPI 3.0. However, reading the below, maybe someone needs to have an in-depth look at the code for the collectionFormat, or at least clean it up? Also, is my assumption correct, that 2 should handle both OpenAPI 3.0 and 2.0, or how should that be handled? // TDOO revise collectionFormat
String collectionFormat = null;
if (ModelUtils.isArraySchema(parameterSchema)) { // for array parameter
final ArraySchema arraySchema = (ArraySchema) parameterSchema;
Schema inner = arraySchema.getItems();
if (inner == null) {
LOGGER.warn("warning! No inner type supplied for array parameter \"" + parameter.getName() + "\", using String");
inner = new StringSchema().description("//TODO automatically added by openapi-generator due to missing iner type definition in the spec");
arraySchema.setItems(inner);
}
collectionFormat = getCollectionFormat(parameter);
// default to csv:
collectionFormat = StringUtils.isEmpty(collectionFormat) ? "csv" : collectionFormat;
CodegenProperty codegenProperty = fromProperty("inner", inner);
codegenParameter.items = codegenProperty;
codegenParameter.mostInnerItems = codegenProperty.mostInnerItems;
codegenParameter.baseType = codegenProperty.dataType;
codegenParameter.isContainer = true;
codegenParameter.isListContainer = true;
// recursively add import
while (codegenProperty != null) {
imports.add(codegenProperty.baseType);
codegenProperty = codegenProperty.items;
}
} else if (ModelUtils.isMapSchema(parameterSchema)) { // for map parameter
CodegenProperty codegenProperty = fromProperty("inner", ModelUtils.getAdditionalProperties(parameterSchema));
codegenParameter.items = codegenProperty;
codegenParameter.mostInnerItems = codegenProperty.mostInnerItems;
codegenParameter.baseType = codegenProperty.dataType;
codegenParameter.isContainer = true;
codegenParameter.isMapContainer = true;
// recursively add import
while (codegenProperty != null) {
imports.add(codegenProperty.baseType);
codegenProperty = codegenProperty.items;
}
}
/* TODO revise the logic below
} else {
Map<PropertyId, Object> args = new HashMap<PropertyId, Object>();
String format = qp.getFormat();
args.put(PropertyId.ENUM, qp.getEnum());
property = PropertyBuilder.build(type, format, args);
}
*/
CodegenProperty codegenProperty = fromProperty(parameter.getName(), parameterSchema);
// TODO revise below which seems not working
//if (parameterSchema.getRequired() != null && !parameterSchema.getRequired().isEmpty() && parameterSchema.getRequired().contains(codegenProperty.baseName)) {
codegenProperty.required = Boolean.TRUE.equals(parameter.getRequired()) ? true : false;
//}
//codegenProperty.required = true; |
@jimschubert could you help here please? |
Hi guys any update about this ? |
Thanks for bumping this. I didn't see that I was tagged above. I'll reach out and see if someone knows if this is being fixed elsewhere. |
I'll take a look later today. |
I don't think the
What does the payload looks like? Heads up: When you said it works fine with swagger codegen 2.3.1. Do you only mean the code generation does not throw error/warning? or you're referring to the auto-generated client able to upload multiple files through POST operation to the endpoint? |
@anthowm please declare it inline for the time being as |
I currently use OAS 3.0 this is my yml for 1 image only (Generator version 3.3.3
With this spec I get something like (name?: string, type?: string, imageUrls?: Blob, observe?: 'events', reportProgress?: boolean) in my typescript service For Array
With this spec I get something like (name?: string, type?: string, imageUrls?: Blob[], observe?: 'events', reportProgress?: boolean) in my typescript service This time I tested, it send to my server as [object File] so I guess now is working but my server get empty array ( I'm using express so maybe I miss something I will update you ASAP). When you said it works fine with swagger codegen 2.3.1. Do you only mean the code generation does not throw error/warning? I mean to this. I get same error later. |
@anthowm can you ping me via https://gitter.im (ID: wing328) when you've time this week to work together on the issue? My timezone is +0800. |
@wing328 : Is it ok if I contact you tomorrow as well? The question is, is it required to use openapi 3.0 specification instead of openapi 2.0? As I'm saying, the variable is set incorrectly / the openapi 2.0 code results in an incorrect default behaviour and is not parsed at all. You can see in my first comment (here: #1458 (comment) ) the client code generated by swagger-codegen compared to openapi-codegen. In swagger, the unknown_base type issue is not occurring, furthermore the files are appended in a better way than in openapi generator:
@anthowm :
Because, if it's empty, the browser will correctly say that the form boundary is the token ( As soon as the issue with OpenAPI 2.0 selecting the wrong code branch is fixed, I can create a pull request removing this code, which should then work. |
@akehir |
any update here? the issue still exists in the current version |
This is working with OAS 3 |
Any tips how to deal with UNKNOWN_BASE_TYPE? I get it both in |
I think this should be fixed in the latest master. Please pull the latest to give it a try. |
Description
We have an api, where the resource consumes in the post body an array of files. While I'm not sure if it's fully spec compliant, the swagger codegen generates workable code , but the openapi-generator does not find a model / schema, and uses the
UNKNOWN_BASE_TYPE
.Generated Code from openapi-generator
Generated Code from swagger-generator
Generated Code from openapi-generator, if consumes is set to
multipart/form-data
Working code example
openapi-generator version
openapi-generator: version 3.3.2 -> it works in swagger-codegen 2.3.1
OpenAPI declaration file content or url
Error message during code-generation
Command line used for generation
mvn test
mvn verify
The source is spring boot / java, with the following method signature:
Steps to reproduce
Generate the code from the json file using openapi-generator generates the incorrect code with an
This will throw
TypeError: files.join is not a function
. Also, the assumtion that csv is going to be used is incorrect.Therefore, this should probably be changed to something like the below:
If that's fixed, the next error will be at spring side with
org.springframework.web.multipart.MultipartException: Current request is not a multipart request
.Since useForm is false, the sent content will not be correctly, at least if it's not a text / csv file.
Let me know your thoughts @macjohnny @wing328, I can probably create a template which will hopefully generate a more correct api.
The text was updated successfully, but these errors were encountered: