Skip to content

Commit 5b6d224

Browse files
committed
Merge pull request #1747 from wing328/add_golang
[Go] Add Go API client generator
2 parents 03b463b + 20e531d commit 5b6d224

File tree

17 files changed

+1298
-0
lines changed

17 files changed

+1298
-0
lines changed

bin/go-petstore.sh

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/sh
2+
3+
SCRIPT="$0"
4+
5+
while [ -h "$SCRIPT" ] ; do
6+
ls=`ls -ld "$SCRIPT"`
7+
link=`expr "$ls" : '.*-> \(.*\)$'`
8+
if expr "$link" : '/.*' > /dev/null; then
9+
SCRIPT="$link"
10+
else
11+
SCRIPT=`dirname "$SCRIPT"`/"$link"
12+
fi
13+
done
14+
15+
if [ ! -d "${APP_DIR}" ]; then
16+
APP_DIR=`dirname "$SCRIPT"`/..
17+
APP_DIR=`cd "${APP_DIR}"; pwd`
18+
fi
19+
20+
executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
21+
22+
if [ ! -f "$executable" ]
23+
then
24+
mvn clean package
25+
fi
26+
27+
# if you've executed sbt assembly previously it will use that instead.
28+
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
29+
ags="$@ generate -t modules/swagger-codegen/src/main/resources/go -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l go -o samples/client/petstore/go"
30+
31+
java $JAVA_OPTS -jar $executable $ags

bin/windows/go-petstore.bat

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
2+
3+
If Not Exist %executable% (
4+
mvn clean package
5+
)
6+
7+
set JAVA_OPTS=%JAVA_OPTS% -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties
8+
set ags=generate -t modules\swagger-codegen\src\main\resources\go -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l go -o samples\client\petstore\go
9+
10+
java %JAVA_OPTS% -jar %executable% %ags%
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
package io.swagger.codegen.languages;
2+
3+
import io.swagger.codegen.*;
4+
import io.swagger.models.properties.ArrayProperty;
5+
import io.swagger.models.properties.MapProperty;
6+
import io.swagger.models.properties.Property;
7+
8+
import java.io.File;
9+
import java.util.*;
10+
11+
import org.apache.commons.lang.StringUtils;
12+
13+
import org.slf4j.Logger;
14+
import org.slf4j.LoggerFactory;
15+
16+
public class GoClientCodegen extends DefaultCodegen implements CodegenConfig {
17+
static Logger LOGGER = LoggerFactory.getLogger(GoClientCodegen.class);
18+
19+
protected String packageName = "swagger";
20+
protected String packageVersion = "1.0.0";
21+
22+
public CodegenType getTag() {
23+
return CodegenType.CLIENT;
24+
}
25+
26+
public String getName() {
27+
return "go";
28+
}
29+
30+
public String getHelp() {
31+
return "Generates a Go client library (beta).";
32+
}
33+
34+
public GoClientCodegen() {
35+
super();
36+
outputFolder = "generated-code/go";
37+
modelTemplateFiles.put("model.mustache", ".go");
38+
apiTemplateFiles.put("api.mustache", ".go");
39+
templateDir = "go";
40+
41+
reservedWords = new HashSet<String> (
42+
Arrays.asList(
43+
"break", "default", "func", "interface", "select",
44+
"case", "defer", "go", "map", "struct",
45+
"chan", "else", "goto", "package", "switch",
46+
"const", "fallthrough", "if", "range", "type",
47+
"continue", "for", "import", "return", "var")
48+
);
49+
50+
defaultIncludes = new HashSet<String>(
51+
Arrays.asList(
52+
"map",
53+
"array")
54+
);
55+
56+
languageSpecificPrimitives = new HashSet<String>(
57+
Arrays.asList(
58+
"string",
59+
"bool",
60+
"uint",
61+
"uint32",
62+
"uint64",
63+
"int",
64+
"int32",
65+
"int64",
66+
"float32",
67+
"float64",
68+
"complex64",
69+
"complex128",
70+
"rune",
71+
"byte")
72+
);
73+
74+
instantiationTypes.clear();
75+
/*instantiationTypes.put("array", "GoArray");
76+
instantiationTypes.put("map", "GoMap");*/
77+
78+
typeMapping.clear();
79+
typeMapping.put("integer", "int32");
80+
typeMapping.put("long", "int64");
81+
typeMapping.put("float", "float32");
82+
typeMapping.put("double", "float64");
83+
typeMapping.put("boolean", "bool");
84+
typeMapping.put("string", "string");
85+
typeMapping.put("Date", "time.Time");
86+
typeMapping.put("DateTime", "time.Time");
87+
typeMapping.put("password", "string");
88+
typeMapping.put("File", "*os.File");
89+
typeMapping.put("file", "*os.File");
90+
// map binary to string as a workaround
91+
// the correct solution is to use []byte
92+
typeMapping.put("binary", "string");
93+
94+
importMapping = new HashMap<String, String>();
95+
importMapping.put("time.Time", "time");
96+
importMapping.put("*os.File", "os");
97+
98+
cliOptions.clear();
99+
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "Go package name (convention: lowercase).")
100+
.defaultValue("swagger"));
101+
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "Go package version.")
102+
.defaultValue("1.0.0"));
103+
104+
}
105+
106+
@Override
107+
public void processOpts() {
108+
//super.processOpts();
109+
110+
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
111+
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
112+
}
113+
else {
114+
setPackageName("swagger");
115+
}
116+
117+
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
118+
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
119+
}
120+
else {
121+
setPackageVersion("1.0.0");
122+
}
123+
124+
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
125+
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
126+
127+
modelPackage = packageName;
128+
apiPackage = packageName;
129+
130+
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
131+
}
132+
133+
@Override
134+
public String escapeReservedWord(String name) {
135+
return "_" + name;
136+
}
137+
138+
@Override
139+
public String apiFileFolder() {
140+
return outputFolder + File.separator + packageName;
141+
}
142+
143+
public String modelFileFolder() {
144+
return outputFolder + File.separator + packageName;
145+
}
146+
147+
@Override
148+
public String toVarName(String name) {
149+
// replace - with _ e.g. created-at => created_at
150+
name = name.replaceAll("-", "_");
151+
152+
// if it's all uppper case, do nothing
153+
if (name.matches("^[A-Z_]*$"))
154+
return name;
155+
156+
// camelize (lower first character) the variable name
157+
// pet_id => PetId
158+
name = camelize(name);
159+
160+
// for reserved word or word starting with number, append _
161+
if(reservedWords.contains(name) || name.matches("^\\d.*"))
162+
name = escapeReservedWord(name);
163+
164+
return name;
165+
}
166+
167+
@Override
168+
public String toParamName(String name) {
169+
// should be the same as variable name
170+
return toVarName(name);
171+
}
172+
173+
@Override
174+
public String toModelName(String name) {
175+
// model name cannot use reserved keyword, e.g. return
176+
if(reservedWords.contains(name))
177+
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
178+
179+
// camelize the model name
180+
// phone_number => PhoneNumber
181+
return camelize(name);
182+
}
183+
184+
@Override
185+
public String toModelFilename(String name) {
186+
// should be the same as the model name
187+
return toModelName(name);
188+
}
189+
190+
@Override
191+
public String getTypeDeclaration(Property p) {
192+
if(p instanceof ArrayProperty) {
193+
ArrayProperty ap = (ArrayProperty) p;
194+
Property inner = ap.getItems();
195+
return "[]" + getTypeDeclaration(inner);
196+
}
197+
else if (p instanceof MapProperty) {
198+
MapProperty mp = (MapProperty) p;
199+
Property inner = mp.getAdditionalProperties();
200+
201+
return getSwaggerType(p) + "[string]" + getTypeDeclaration(inner);
202+
}
203+
return super.getTypeDeclaration(p);
204+
}
205+
206+
@Override
207+
public String getSwaggerType(Property p) {
208+
String swaggerType = super.getSwaggerType(p);
209+
String type = null;
210+
if(typeMapping.containsKey(swaggerType)) {
211+
type = typeMapping.get(swaggerType);
212+
if(languageSpecificPrimitives.contains(type))
213+
return (type);
214+
}
215+
else
216+
type = swaggerType;
217+
return type;
218+
}
219+
220+
@Override
221+
public String toOperationId(String operationId) {
222+
// method name cannot use reserved keyword, e.g. return
223+
if(reservedWords.contains(operationId))
224+
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
225+
226+
return camelize(operationId);
227+
}
228+
229+
@Override
230+
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
231+
@SuppressWarnings("unchecked")
232+
Map<String, Object> objectMap = (Map<String, Object>) objs.get("operations");
233+
@SuppressWarnings("unchecked")
234+
List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
235+
for (CodegenOperation operation : operations) {
236+
// http method verb conversion (e.g. PUT => Put)
237+
operation.httpMethod = camelize(operation.httpMethod.toLowerCase());
238+
}
239+
240+
// remove model imports to avoid error
241+
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
242+
if (imports == null)
243+
return objs;
244+
245+
Iterator<Map<String, String>> iterator = imports.iterator();
246+
while (iterator.hasNext()) {
247+
String _import = iterator.next().get("import");
248+
if (_import.startsWith(apiPackage()))
249+
iterator.remove();
250+
}
251+
252+
return objs;
253+
}
254+
255+
@Override
256+
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
257+
// remove model imports to avoid error
258+
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
259+
final String prefix = modelPackage();
260+
Iterator<Map<String, String>> iterator = imports.iterator();
261+
while (iterator.hasNext()) {
262+
String _import = iterator.next().get("import");
263+
if (_import.startsWith(prefix))
264+
iterator.remove();
265+
}
266+
return objs;
267+
}
268+
269+
@Override
270+
protected boolean needToImport(String type) {
271+
return !defaultIncludes.contains(type)
272+
&& !languageSpecificPrimitives.contains(type);
273+
}
274+
275+
public void setPackageName(String packageName) {
276+
this.packageName = packageName;
277+
}
278+
279+
public void setPackageVersion(String packageVersion) {
280+
this.packageVersion = packageVersion;
281+
}
282+
283+
}

modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ io.swagger.codegen.languages.CSharpClientCodegen
44
io.swagger.codegen.languages.DartClientCodegen
55
io.swagger.codegen.languages.FlashClientCodegen
66
io.swagger.codegen.languages.FlaskConnexionCodegen
7+
io.swagger.codegen.languages.GoClientCodegen
78
io.swagger.codegen.languages.JavaClientCodegen
89
io.swagger.codegen.languages.JavascriptClientCodegen
910
io.swagger.codegen.languages.JaxRSServerCodegen
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Go API client for {{packageName}}
2+
3+
## Overview
4+
This API client was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the [swagger-spec](https://github.com/swagger-api/swagger-spec) from a remote server, you can easily generate an API client.
5+
6+
7+
## Installation
8+
Put the package under your project folder and add the following in import:
9+
```
10+
"./{{packageName}}"
11+
```
12+

0 commit comments

Comments
 (0)