1
- part of api;
1
+ part of { {pubName} }.api;
2
+
3
+ class QueryParam {
4
+ String name;
5
+ String value;
6
+
7
+ QueryParam(this.name, this.value);
8
+ }
2
9
3
10
class ApiClient {
4
- static ApiClient defaultApiClient = new ApiClient();
11
+
12
+ String basePath;
13
+ var client = new {{#browserClient} }Browser{ {/browserClient} }Client();
5
14
6
15
Map<String , String > _defaultHeaderMap = { } ;
7
16
Map<String , Authentication > _authentications = { } ;
8
- static final dson = new Dartson.JSON();
17
+
18
+ final dson = new Dartson.JSON();
9
19
final DateFormat _dateFormatter = new DateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
10
20
11
- ApiClient() {
21
+ final _RegList = new RegExp(r'^List<(.*)>$');
22
+ final _RegMap = new RegExp(r'^Map<String ,(.*) >$');
23
+
24
+ ApiClient({ this.basePath: " {{{basePath}}}" } ) {
12
25
// Setup authentications (key: authentication name, value: authentication).{{#authMethods} }{ {#isBasic} }
13
26
_authentications['{ {name} }'] = new HttpBasicAuth();{ {/isBasic} }{ {#isApiKey} }
14
27
_authentications['{ {name} }'] = new ApiKeyAuth({ {#isKeyInHeader} }"header"{ {/isKeyInHeader} }{ {^isKeyInHeader} }"query"{ {/isKeyInHeader} }, "{ {keyParamName} }");{ {/isApiKey} }{ {#isOAuth} }
@@ -37,43 +50,57 @@ class ApiClient {
37
50
}
38
51
}
39
52
40
- static dynamic deserialize(String json, dynamic clazz) {
41
- var result = json;
42
-
53
+ dynamic _deserialize(dynamic value, String targetType) {
43
54
try {
44
- var decodedJson = JSON.decode(json);
45
-
46
- if (decodedJson is List) {
47
- result = [];
48
- for(var obj in decodedJson) {
49
- result.add(_createEntity(obj, clazz));
50
- }
51
- } else {
52
- result = _createEntity(json, clazz);
55
+ switch (targetType) {
56
+ case ' String' :
57
+ return ' $value' ;
58
+ case ' int' :
59
+ return value is int ? value : int.parse(' $value' );
60
+ case ' bool' :
61
+ return value is bool ? value : ' $value' .toLowerCase() == ' true' ;
62
+ case ' double' :
63
+ return value is double ? value : double.parse(' $value' );
64
+ {{#models} }
65
+ { {#model} }
66
+ case '{ {classname} }':
67
+ return dson.map(value, new { {classname} }());
68
+ { {/model} }
69
+ { {/models} }
70
+ default:
71
+ {
72
+ Match match;
73
+ if (value is List &&
74
+ (match = _RegList.firstMatch(targetType)) != null) {
75
+ var valueL = value as List;
76
+ var newTargetType = match[1];
77
+ return valueL.map((v) => _deserialize(v, newTargetType)).toList();
78
+ } else if (value is Map &&
79
+ (match = _RegMap.firstMatch(targetType)) != null) {
80
+ var valueM = value as Map;
81
+ var newTargetType = match[1];
82
+ return new Map.fromIterables(valueM.keys,
83
+ valueM.values.map((v) => _deserialize(v, newTargetType)));
84
+ }
85
+ }
53
86
}
54
- } on FormatException {
55
- // Just return the passed in value
87
+ } catch(e) {
88
+ // Just throw the ApiException below
56
89
}
57
-
58
- return result;
90
+ throw new ApiException(500, 'Could not find a suitable class for deserialization');
59
91
}
60
92
61
- static dynamic _createEntity(dynamic json, dynamic clazz) {
62
- bool isMap = json is Map;
63
-
64
- switch (clazz) {
65
- {{#models} }
66
- { {#model} }
67
- case { {classname} }:
68
- return isMap ? dson.map(json, new { {classname} }()) : dson.decode(json, new { {classname} }());
69
- { {/model} }
70
- { {/models} }
71
- default:
72
- throw new ApiException(500, 'Could not find a suitable class for deserialization');
73
- }
93
+ dynamic deserialize(String json, String targetType) {
94
+ // Remove all spaces. Necessary for reg expressions as well.
95
+ targetType = targetType.replaceAll(' ' , ' ' );
96
+
97
+ if (targetType == ' String' ) return json;
98
+
99
+ var decodedJson = JSON.decode(json);
100
+ return _deserialize(decodedJson, targetType);
74
101
}
75
102
76
- static String serialize(Object obj) {
103
+ String serialize(Object obj) {
77
104
String serialized = ' ' ;
78
105
if (obj == null) {
79
106
serialized = ' ' ;
@@ -85,76 +112,59 @@ class ApiClient {
85
112
return serialized;
86
113
}
87
114
88
- Future<Response > invokeAPI( String host,
89
- String path,
90
- String method,
91
- Map<String , String > queryParams,
92
- Object body,
93
- Map<String , String > headerParams,
94
- Map<String , String > formParams,
95
- String contentType,
96
- List<String > authNames) {
97
-
98
- updateParamsForAuth(authNames, queryParams, headerParams);
99
-
100
- var client = new {{#browserClient} }Browser{ {/browserClient} }Client();
101
-
102
- StringBuffer sb = new StringBuffer();
103
-
104
- for(String key in queryParams.keys) {
105
- String value = queryParams[key];
106
- if (value != null){
107
- if (sb.toString().length == 0) {
108
- sb.write(" ?" );
109
- } else {
110
- sb.write(" &" );
111
- }
112
- sb.write(key);
113
- sb.write("=");
114
- sb.write(value);
115
- }
116
- }
117
- String querystring = sb.toString();
115
+ // We don't use a Map<String , String > for queryParams.
116
+ // If collectionFormat is 'multi' a key might appear multiple times.
117
+ Future<Response > invokeAPI(String path,
118
+ String method,
119
+ List<QueryParam > queryParams,
120
+ Object body,
121
+ Map<String , String > headerParams,
122
+ Map<String , String > formParams,
123
+ String contentType,
124
+ List<String > authNames) async {
125
+
126
+ _updateParamsForAuth(authNames, queryParams, headerParams);
127
+
128
+ var ps = queryParams.where((p) => p.value != null).map((p) => ' ${p.name}=${p.value}' );
129
+ String queryString = ps.isNotEmpty ?
130
+ ' ?' + ps.join(' &' ) :
131
+ ' ' ;
118
132
119
- String url = host + path + querystring ;
133
+ String url = basePath + path + queryString ;
120
134
121
135
headerParams.addAll(_defaultHeaderMap);
122
136
headerParams[' Content-Type' ] = contentType;
123
137
124
- var completer = new Completer();
125
-
126
138
if (body is MultipartRequest) {
127
139
var request = new MultipartRequest(method, Uri.parse(url));
128
140
request.fields.addAll(body.fields);
129
141
request.files.addAll(body.files);
130
142
request.headers.addAll(body.headers);
131
143
request.headers.addAll(headerParams);
132
- client.send(request).then((response) => completer.complete(Response.fromStream(response)));
144
+ var response = await client.send(request);
145
+ return Response.fromStream(response);
133
146
} else {
134
147
var msgBody = contentType == " application/x-www-form-urlencoded" ? formParams : serialize(body);
135
148
switch (method) {
136
- case " GET" :
137
- return client.get(url, headers: headerParams);
138
149
case " POST" :
139
150
return client.post(url, headers: headerParams, body: msgBody);
140
151
case " PUT" :
141
152
return client.put(url, headers: headerParams, body: msgBody);
142
153
case " DELETE" :
143
154
return client.delete(url, headers: headerParams);
155
+ default :
156
+ return client.get(url, headers: headerParams);
144
157
}
145
158
}
146
-
147
- return completer.future;
148
159
}
149
160
150
161
/// Update query and header parameters based on authentication settings.
151
162
/// @param authNames The authentications to apply
152
- void updateParamsForAuth (List<String > authNames, Map< String , String > queryParams, Map<String , String > headerParams) {
163
+ void _updateParamsForAuth (List<String > authNames, List< QueryParam > queryParams, Map<String , String > headerParams) {
153
164
authNames.forEach((authName) {
154
165
Authentication auth = _authentications[authName];
155
166
if (auth == null) throw new ArgumentError(" Authentication undefined: " + authName);
156
167
auth.applyToParams(queryParams, headerParams);
157
168
} );
158
169
}
159
-
160
170
}
0 commit comments