forked from loafle/openapi-generator-original
Support binary input and output (for body parameters or responses with type "string" and format "binary". Implemented for Java.
This commit is contained in:
parent
f2df26f6e6
commit
d4b4fe4b47
@ -7,7 +7,7 @@ import java.util.List;
|
||||
|
||||
public class CodegenParameter {
|
||||
public Boolean isFormParam, isQueryParam, isPathParam, isHeaderParam,
|
||||
isCookieParam, isBodyParam, isFile, notFile, hasMore, isContainer, secondaryParam;
|
||||
isCookieParam, isBodyParam, isFile, notFile, hasMore, isContainer, secondaryParam, isBinary;
|
||||
public String baseName, paramName, dataType, collectionFormat, description, baseType, defaultValue;
|
||||
public String jsonSchema;
|
||||
public boolean isEnum;
|
||||
|
@ -15,6 +15,7 @@ public class CodegenResponse {
|
||||
public Boolean primitiveType;
|
||||
public Boolean isMapContainer;
|
||||
public Boolean isListContainer;
|
||||
public Boolean isBinary;
|
||||
public Object schema;
|
||||
public String jsonSchema;
|
||||
|
||||
|
@ -27,6 +27,7 @@ import io.swagger.models.parameters.SerializableParameter;
|
||||
import io.swagger.models.properties.AbstractNumericProperty;
|
||||
import io.swagger.models.properties.ArrayProperty;
|
||||
import io.swagger.models.properties.BooleanProperty;
|
||||
import io.swagger.models.properties.ByteArrayProperty;
|
||||
import io.swagger.models.properties.DateProperty;
|
||||
import io.swagger.models.properties.DateTimeProperty;
|
||||
import io.swagger.models.properties.DecimalProperty;
|
||||
@ -308,6 +309,8 @@ public class DefaultCodegen {
|
||||
typeMapping.put("double", "Double");
|
||||
typeMapping.put("object", "Object");
|
||||
typeMapping.put("integer", "Integer");
|
||||
typeMapping.put("ByteArray", "byte[]");
|
||||
|
||||
|
||||
instantiationTypes = new HashMap<String, String>();
|
||||
|
||||
@ -444,6 +447,8 @@ public class DefaultCodegen {
|
||||
String datatype = null;
|
||||
if (p instanceof StringProperty) {
|
||||
datatype = "string";
|
||||
} else if (p instanceof ByteArrayProperty) {
|
||||
datatype = "ByteArray";
|
||||
} else if (p instanceof BooleanProperty) {
|
||||
datatype = "boolean";
|
||||
} else if (p instanceof DateProperty) {
|
||||
@ -965,6 +970,7 @@ public class DefaultCodegen {
|
||||
}
|
||||
}
|
||||
r.dataType = cm.datatype;
|
||||
r.isBinary = cm.datatype.equals("byte[]");
|
||||
if (cm.isContainer != null) {
|
||||
r.simpleType = false;
|
||||
r.containerType = cm.containerType;
|
||||
@ -1061,12 +1067,17 @@ public class DefaultCodegen {
|
||||
p.dataType = getTypeDeclaration(cm.classname);
|
||||
imports.add(p.dataType);
|
||||
} else {
|
||||
// TODO: missing format, so this will not always work
|
||||
Property prop = PropertyBuilder.build(impl.getType(), null, null);
|
||||
Property prop = PropertyBuilder.build(impl.getType(), impl.getFormat(), null);
|
||||
prop.setRequired(bp.getRequired());
|
||||
CodegenProperty cp = fromProperty("property", prop);
|
||||
if (cp != null) {
|
||||
p.dataType = cp.datatype;
|
||||
if (p.dataType.equals("byte[]")) {
|
||||
p.isBinary = true;
|
||||
}
|
||||
else {
|
||||
p.isBinary = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (model instanceof ArrayModel) {
|
||||
|
@ -64,7 +64,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
"Integer",
|
||||
"Long",
|
||||
"Float",
|
||||
"Object")
|
||||
"Object",
|
||||
"byte[]")
|
||||
);
|
||||
instantiationTypes.put("array", "ArrayList");
|
||||
instantiationTypes.put("map", "HashMap");
|
||||
@ -129,7 +130,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
if (additionalProperties.containsKey("localVariablePrefix")) {
|
||||
this.setLocalVariablePrefix((String) additionalProperties.get("localVariablePrefix"));
|
||||
}
|
||||
|
||||
|
||||
this.sanitizeConfig();
|
||||
|
||||
final String invokerFolder = (sourceFolder + File.separator + invokerPackage).replace(".", File.separator);
|
||||
@ -266,7 +267,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
if (typeMapping.containsKey(swaggerType)) {
|
||||
type = typeMapping.get(swaggerType);
|
||||
if (languageSpecificPrimitives.contains(type)) {
|
||||
return toModelName(type);
|
||||
return type;
|
||||
}
|
||||
} else {
|
||||
type = swaggerType;
|
||||
@ -363,7 +364,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
public void setLocalVariablePrefix(String localVariablePrefix) {
|
||||
this.localVariablePrefix = localVariablePrefix;
|
||||
}
|
||||
|
||||
|
||||
private String sanitizePackageName(String packageName) {
|
||||
packageName = packageName.trim();
|
||||
packageName = packageName.replaceAll("[^a-zA-Z0-9_\\.]", "_");
|
||||
|
@ -30,6 +30,7 @@ import java.net.URLEncoder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.DataInputStream;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
@ -385,21 +386,12 @@ public class ApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke API by sending HTTP request with the given options.
|
||||
*
|
||||
* @param path The sub-path of the HTTP URL
|
||||
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
|
||||
* @param queryParams The query parameters
|
||||
* @param body The request body object
|
||||
* @param headerParams The header parameters
|
||||
* @param formParams The form parameters
|
||||
* @param accept The request's Accept header
|
||||
* @param contentType The request's Content-Type header
|
||||
* @param authNames The authentications to apply
|
||||
* @return The response body in type of string
|
||||
*/
|
||||
public String invokeAPI(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, String> formParams, String accept, String contentType, String[] authNames) throws ApiException {
|
||||
private ClientResponse getAPIResponse(String path, String method, List<Pair> queryParams, Object body, byte[] binaryBody, Map<String, String> headerParams, Map<String, String> formParams, String accept, String contentType, String[] authNames) throws ApiException {
|
||||
|
||||
if (body != null && binaryBody != null){
|
||||
throw new ApiException(500, "either body or binaryBody must be null");
|
||||
}
|
||||
|
||||
updateParamsForAuth(authNames, queryParams, headerParams);
|
||||
|
||||
Client client = getClient();
|
||||
@ -446,7 +438,10 @@ public class ApiClient {
|
||||
response = builder.type(contentType).post(ClientResponse.class,
|
||||
encodedFormParams);
|
||||
} else if (body == null) {
|
||||
response = builder.post(ClientResponse.class, null);
|
||||
if(binaryBody == null)
|
||||
response = builder.post(ClientResponse.class, null);
|
||||
else
|
||||
response = builder.type(contentType).post(ClientResponse.class, binaryBody);
|
||||
} else if(body instanceof FormDataMultiPart) {
|
||||
response = builder.type(contentType).post(ClientResponse.class, body);
|
||||
}
|
||||
@ -460,7 +455,10 @@ public class ApiClient {
|
||||
response = builder.type(contentType).put(ClientResponse.class,
|
||||
encodedFormParams);
|
||||
} else if(body == null) {
|
||||
response = builder.put(ClientResponse.class, serialize(body));
|
||||
if(binaryBody == null)
|
||||
response = builder.put(ClientResponse.class, null);
|
||||
else
|
||||
response = builder.type(contentType).put(ClientResponse.class, binaryBody);
|
||||
} else {
|
||||
response = builder.type(contentType).put(ClientResponse.class, serialize(body));
|
||||
}
|
||||
@ -472,7 +470,10 @@ public class ApiClient {
|
||||
response = builder.type(contentType).delete(ClientResponse.class,
|
||||
encodedFormParams);
|
||||
} else if(body == null) {
|
||||
response = builder.delete(ClientResponse.class);
|
||||
if(binaryBody == null)
|
||||
response = builder.delete(ClientResponse.class);
|
||||
else
|
||||
response = builder.type(contentType).delete(ClientResponse.class, binaryBody);
|
||||
} else {
|
||||
response = builder.type(contentType).delete(ClientResponse.class, serialize(body));
|
||||
}
|
||||
@ -480,6 +481,27 @@ public class ApiClient {
|
||||
else {
|
||||
throw new ApiException(500, "unknown method type " + method);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke API by sending HTTP request with the given options.
|
||||
*
|
||||
* @param path The sub-path of the HTTP URL
|
||||
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
|
||||
* @param queryParams The query parameters
|
||||
* @param body The request body object - if it is not binary, otherwise null
|
||||
* @param binaryBody The request body object - if it is binary, otherwise null
|
||||
* @param headerParams The header parameters
|
||||
* @param formParams The form parameters
|
||||
* @param accept The request's Accept header
|
||||
* @param contentType The request's Content-Type header
|
||||
* @param authNames The authentications to apply
|
||||
* @return The response body in type of string
|
||||
*/
|
||||
public String invokeAPI(String path, String method, List<Pair> queryParams, Object body, byte[] binaryBody, Map<String, String> headerParams, Map<String, String> formParams, String accept, String contentType, String[] authNames) throws ApiException {
|
||||
|
||||
ClientResponse response = getAPIResponse(path, method, queryParams, body, binaryBody, headerParams, formParams, accept, contentType, authNames);
|
||||
|
||||
if(response.getStatusInfo() == ClientResponse.Status.NO_CONTENT) {
|
||||
return null;
|
||||
@ -511,6 +533,58 @@ public class ApiClient {
|
||||
respBody);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Invoke API by sending HTTP request with the given options - return binary result
|
||||
*
|
||||
* @param path The sub-path of the HTTP URL
|
||||
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
|
||||
* @param queryParams The query parameters
|
||||
* @param body The request body object - if it is not binary, otherwise null
|
||||
* @param binaryBody The request body object - if it is binary, otherwise null
|
||||
* @param headerParams The header parameters
|
||||
* @param formParams The form parameters
|
||||
* @param accept The request's Accept header
|
||||
* @param contentType The request's Content-Type header
|
||||
* @param authNames The authentications to apply
|
||||
* @return The response body in type of string
|
||||
*/
|
||||
public byte[] invokeBinaryAPI(String path, String method, List<Pair> queryParams, Object body, byte[] binaryBody, Map<String, String> headerParams, Map<String, String> formParams, String accept, String contentType, String[]authNames) throws ApiException {
|
||||
|
||||
ClientResponse response = getAPIResponse(path, method, queryParams, body, binaryBody, headerParams, formParams, accept, contentType, authNames);
|
||||
|
||||
if(response.getStatusInfo() == ClientResponse.Status.NO_CONTENT) {
|
||||
return null;
|
||||
}
|
||||
else if(response.getStatusInfo().getFamily() == Family.SUCCESSFUL) {
|
||||
if(response.hasEntity()) {
|
||||
DataInputStream stream = new DataInputStream(response.getEntityInputStream());
|
||||
byte[] data = new byte[response.getLength()];
|
||||
try {
|
||||
stream.readFully(data);
|
||||
} catch (IOException ex) {
|
||||
throw new ApiException(500, "Error obtaining binary response data");
|
||||
}
|
||||
return data;
|
||||
}
|
||||
else {
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
String message = "error";
|
||||
if(response.hasEntity()) {
|
||||
try{
|
||||
message = String.valueOf(response.getEntity(String.class));
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
// e.printStackTrace();
|
||||
}
|
||||
}
|
||||
throw new ApiException(
|
||||
response.getStatusInfo().getStatusCode(),
|
||||
message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update query and header parameters based on authentication settings.
|
||||
|
@ -50,16 +50,16 @@ public class {{classname}} {
|
||||
{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
|
||||
*/
|
||||
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}} ({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {
|
||||
Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
|
||||
Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{^isBinary}}{{paramName}}{{/isBinary}}{{#isBinary}}null{{/isBinary}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
|
||||
byte[] {{localVariablePrefix}}postBinaryBody = {{#bodyParam}}{{#isBinary}}{{paramName}}{{/isBinary}}{{^isBinary}}null{{/isBinary}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
|
||||
{{#allParams}}{{#required}}
|
||||
// verify the required parameter '{{paramName}}' is set
|
||||
if ({{paramName}} == null) {
|
||||
throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{nickname}}");
|
||||
}
|
||||
{{/required}}{{/allParams}}
|
||||
|
||||
// verify the required parameter '{{paramName}}' is set
|
||||
if ({{paramName}} == null) {
|
||||
throw new ApiException(400, "Missing the required parameter '{{paramName}}' when calling {{nickname}}");
|
||||
}
|
||||
{{/required}}{{/allParams}}
|
||||
// create path and map variables
|
||||
String {{localVariablePrefix}}path = "{{path}}".replaceAll("\\{format\\}","json"){{#pathParams}}
|
||||
String {{localVariablePrefix}}path = "{{{path}}}".replaceAll("\\{format\\}","json"){{#pathParams}}
|
||||
.replaceAll("\\{" + "{{baseName}}" + "\\}", {{localVariablePrefix}}apiClient.escapeString({{{paramName}}}.toString())){{/pathParams}};
|
||||
|
||||
// query params
|
||||
@ -110,14 +110,29 @@ public class {{classname}} {
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
String[] {{localVariablePrefix}}authNames = new String[] { {{#authMethods}}"{{name}}"{{#hasMore}}, {{/hasMore}}{{/authMethods}} };
|
||||
String {{localVariablePrefix}}response = {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames);
|
||||
if({{localVariablePrefix}}response != null){
|
||||
return {{#returnType}}({{{returnType}}}) {{localVariablePrefix}}apiClient.deserialize({{localVariablePrefix}}response, "{{returnContainer}}", {{returnBaseType}}.class){{/returnType}};
|
||||
}
|
||||
else {
|
||||
return {{#returnType}}null{{/returnType}};
|
||||
}
|
||||
|
||||
{{#responses}}{{#isDefault}}
|
||||
{{#isBinary}}
|
||||
byte[] {{localVariablePrefix}}response = null;
|
||||
{{localVariablePrefix}}response = {{localVariablePrefix}}apiClient.invokeBinaryAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams,{{localVariablePrefix}} postBody, {{localVariablePrefix}}postBinaryBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames);
|
||||
return {{localVariablePrefix}}response;
|
||||
|
||||
{{/isBinary}}
|
||||
{{^isBinary}}
|
||||
|
||||
String {{localVariablePrefix}}response = {{localVariablePrefix}}apiClient.invokeAPI({{localVariablePrefix}}path, "{{httpMethod}}", {{localVariablePrefix}}queryParams, {{localVariablePrefix}}postBody, {{localVariablePrefix}}postBinaryBody, {{localVariablePrefix}}headerParams, {{localVariablePrefix}}formParams, {{localVariablePrefix}}accept, {{localVariablePrefix}}contentType, {{localVariablePrefix}}authNames);
|
||||
if({{localVariablePrefix}}response != null){
|
||||
return {{#returnType}}({{{returnType}}}) {{localVariablePrefix}}apiClient.deserialize({{localVariablePrefix}}response, "{{returnContainer}}", {{returnBaseType}}.class){{/returnType}};
|
||||
}
|
||||
else {
|
||||
return {{#returnType}}null{{/returnType}};
|
||||
}
|
||||
{{/isBinary}}
|
||||
{{/isDefault}}
|
||||
{{/responses}}
|
||||
|
||||
} catch (ApiException ex) {
|
||||
throw ex;
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"description": "This is a sample server Petstore server. You can find out more about Swagger at <a href=\"http://swagger.io\">http://swagger.io</a> or on irc.freenode.net, #swagger. For this sample, you can use the api key \"special-key\" to test the authorization filters",
|
||||
"version": "1.0.0",
|
||||
"title": "Swagger Petstore",
|
||||
"termsOfService": "http://helloreverb.com/terms/",
|
||||
"license": {
|
||||
"name": "Apache 2.0",
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
}
|
||||
},
|
||||
"basePath": "/v2",
|
||||
"schemes": [
|
||||
"http"
|
||||
],
|
||||
"paths": {
|
||||
"/tests/binaryResponse": {
|
||||
"post": {
|
||||
"summary": "Echo test",
|
||||
"operationId": "echotest",
|
||||
"consumes": [
|
||||
"application/octet-stream"
|
||||
],
|
||||
"produces": [
|
||||
"application/octet-stream"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "InputBinaryData",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OutputBinaryData",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "binary"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -139,4 +139,19 @@ class CodegenTest extends FlatSpec with Matchers {
|
||||
val op = codegen.fromOperation(path, "get", p, model.getDefinitions())
|
||||
op.returnType should be("String")
|
||||
}
|
||||
|
||||
it should "return byte array when response format is byte" in {
|
||||
val model = new SwaggerParser()
|
||||
.read("src/test/resources/2_0/binaryDataTest.json")
|
||||
System.err.println("model is " + model);
|
||||
val codegen = new DefaultCodegen()
|
||||
|
||||
val path = "/tests/binaryResponse"
|
||||
val p = model.getPaths().get(path).getPost()
|
||||
val op = codegen.fromOperation(path, "post", p, model.getDefinitions())
|
||||
op.returnType should be("byte[]")
|
||||
op.bodyParam.dataType should be ("byte[]")
|
||||
op.bodyParam.isBinary should equal (true);
|
||||
op.responses.get(0).isBinary should equal(true);
|
||||
}
|
||||
}
|
@ -365,6 +365,28 @@ class JavaModelTest extends FlatSpec with Matchers {
|
||||
val vars = cm.vars
|
||||
cm.classname should be("WithDots")
|
||||
}
|
||||
|
||||
it should "convert a modelwith binary data" in {
|
||||
val model = new ModelImpl()
|
||||
.description("model with binary")
|
||||
.property("inputBinaryData", new ByteArrayProperty());
|
||||
|
||||
val codegen = new JavaClientCodegen()
|
||||
val cm = codegen.fromModel("sample", model)
|
||||
val vars = cm.vars
|
||||
|
||||
vars.get(0).baseName should be ("inputBinaryData")
|
||||
vars.get(0).getter should be ("getInputBinaryData")
|
||||
vars.get(0).setter should be ("setInputBinaryData")
|
||||
vars.get(0).datatype should be ("byte[]")
|
||||
vars.get(0).name should be ("inputBinaryData")
|
||||
vars.get(0).defaultValue should be ("null")
|
||||
vars.get(0).baseType should be ("byte[]")
|
||||
vars.get(0).hasMore should equal (null)
|
||||
vars.get(0).required should equal (null)
|
||||
vars.get(0).isNotContainer should equal (true)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user