Skip to content

Commit 7b6be0e

Browse files
authored
Merge pull request #8721 from while-loop/8426-fix-dart-enum
[Dart] Fix Dart enums (#8426)
2 parents 8c1678b + 5daeacd commit 7b6be0e

File tree

30 files changed

+493
-56
lines changed

30 files changed

+493
-56
lines changed

modules/swagger-codegen/src/main/resources/dart-jaguar/enum.mustache

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
part '{{classFilename}}.jser.dart';
22

3-
@Entity()
43
class {{classname}} {
54
/// The underlying value of this enum member.
65
final {{dataType}} value;
@@ -12,24 +11,22 @@ class {{classname}} {
1211
{{#description}}
1312
/// {{description}}
1413
{{/description}}
15-
static const {{classname}} {{name}} = const {{classname}}._internal({{value}});
14+
static const {{classname}} {{name}} = const {{classname}}._internal({{{value}}});
1615
{{/enumVars}}
1716
{{/allowableValues}}
1817
}
1918

20-
class {{classname}}TypeTransformer extends TypeTransformer<{{classname}}> {
19+
class {{classname}}TypeTransformer {
2120
22-
@override
2321
dynamic encode({{classname}} data) {
2422
return data.value;
2523
}
2624

27-
@override
2825
{{classname}} decode(dynamic data) {
2926
switch (data) {
3027
{{#allowableValues}}
3128
{{#enumVars}}
32-
case {{value}}: return {{classname}}.{{name}};
29+
case {{{value}}}: return {{classname}}.{{name}};
3330
{{/enumVars}}
3431
{{/allowableValues}}
3532
default: throw('Unknown enum value to decode: $data');

modules/swagger-codegen/src/main/resources/dart/api_client.mustache

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,7 @@ class ApiClient {
4444
{{#model}}
4545
case '{{classname}}':
4646
{{#isEnum}}
47-
// Enclose the value in a list so that Dartson can use a transformer
48-
// to decode it.
49-
final listValue = [value];
50-
final List<dynamic> listResult = dson.map(listValue, []);
51-
return listResult[0];
47+
return new {{classname}}.fromJson(value);
5248
{{/isEnum}}
5349
{{^isEnum}}
5450
return new {{classname}}.fromJson(value);
@@ -76,13 +72,13 @@ class ApiClient {
7672
throw new ApiException(500, 'Could not find a suitable class for deserialization');
7773
}
7874

79-
dynamic deserialize(String json, String targetType) {
75+
dynamic deserialize(String jsonVal, String targetType) {
8076
// Remove all spaces. Necessary for reg expressions as well.
8177
targetType = targetType.replaceAll(' ', '');
8278
83-
if (targetType == 'String') return json;
79+
if (targetType == 'String') return jsonVal;
8480
85-
var decodedJson = JSON.decode(json);
81+
var decodedJson = json.decode(jsonVal);
8682
return _deserialize(decodedJson, targetType);
8783
}
8884

@@ -91,7 +87,7 @@ class ApiClient {
9187
if (obj == null) {
9288
serialized = '';
9389
} else {
94-
serialized = JSON.encode(obj);
90+
serialized = json.encode(obj);
9591
}
9692
return serialized;
9793
}

modules/swagger-codegen/src/main/resources/dart/api_helper.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ String parameterToString(dynamic value) {
4242
{{#model}}
4343
{{#isEnum}}
4444
} else if (value is {{classname}}) {
45-
return new {{classname}}TypeTransformer().encode(value).toString();
45+
return {{classname}}.encode(value).toString();
4646
{{/isEnum}}
4747
{{/model}}
4848
{{/models}}

modules/swagger-codegen/src/main/resources/dart/auth/http_basic_auth.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class HttpBasicAuth implements Authentication {
88
@override
99
void applyToParams(List<QueryParam> queryParams, Map<String, String> headerParams) {
1010
String str = (username == null ? "" : username) + ":" + (password == null ? "" : password);
11-
headerParams["Authorization"] = "Basic " + BASE64.encode(UTF8.encode(str));
11+
headerParams["Authorization"] = "Basic " + base64.encode(utf8.encode(str));
1212
}
1313

1414
}
Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,30 @@
1-
@Entity()
21
class {{classname}} {
32
/// The underlying value of this enum member.
4-
final {{dataType}} value;
3+
{{dataType}} value;
54

6-
const {{classname}}._internal(this.value);
5+
{{classname}}._internal(this.value);
76

87
{{#allowableValues}}
98
{{#enumVars}}
109
{{#description}}
1110
/// {{description}}
1211
{{/description}}
13-
static const {{classname}} {{name}} = const {{classname}}._internal({{value}});
12+
static {{classname}} {{name}} = {{classname}}._internal({{{value}}});
1413
{{/enumVars}}
1514
{{/allowableValues}}
16-
}
17-
18-
class {{classname}}TypeTransformer extends TypeTransformer<{{classname}}> {
19-
20-
@override
21-
dynamic encode({{classname}} data) {
22-
return data.value;
23-
}
2415

25-
@override
26-
{{classname}} decode(dynamic data) {
16+
{{classname}}.fromJson(dynamic data) {
2717
switch (data) {
28-
{{#allowableValues}}
29-
{{#enumVars}}
30-
case {{value}}: return {{classname}}.{{name}};
31-
{{/enumVars}}
32-
{{/allowableValues}}
33-
default: throw('Unknown enum value to decode: $data');
18+
{{#allowableValues}}
19+
{{#enumVars}}
20+
case {{{value}}}: value = data; break;
21+
{{/enumVars}}
22+
{{/allowableValues}}
23+
default: throw('Unknown enum value to decode: $data');
3424
}
3525
}
26+
27+
static dynamic encode({{classname}} data) {
28+
return data.value;
29+
}
3630
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package io.swagger.codegen.dart;
2+
3+
import io.swagger.codegen.CodegenModel;
4+
import io.swagger.codegen.CodegenProperty;
5+
import io.swagger.codegen.DefaultCodegen;
6+
import io.swagger.codegen.languages.DartClientCodegen;
7+
import io.swagger.models.ComposedModel;
8+
import io.swagger.models.Model;
9+
import io.swagger.models.ModelImpl;
10+
import io.swagger.models.RefModel;
11+
import io.swagger.models.properties.Property;
12+
import io.swagger.models.properties.StringProperty;
13+
import org.testng.Assert;
14+
import org.testng.annotations.Test;
15+
16+
import java.util.ArrayList;
17+
import java.util.Arrays;
18+
import java.util.HashMap;
19+
import java.util.Map;
20+
21+
@SuppressWarnings("static-method")
22+
public class DartModelEnumTest {
23+
24+
@Test(description = "convert a dart model with an enum")
25+
public void converterTest() {
26+
final StringProperty enumProperty = new StringProperty();
27+
enumProperty.setEnum(Arrays.asList("VALUE1", "VALUE2", "VALUE3"));
28+
final ModelImpl model = new ModelImpl().property("name", enumProperty);
29+
30+
final DefaultCodegen codegen = new DartClientCodegen();
31+
final CodegenModel cm = codegen.fromModel("sample", model);
32+
33+
Assert.assertEquals(cm.vars.size(), 1);
34+
35+
final CodegenProperty enumVar = cm.vars.get(0);
36+
Assert.assertEquals(enumVar.baseName, "name");
37+
Assert.assertEquals(enumVar.datatype, "String");
38+
Assert.assertEquals(enumVar.datatypeWithEnum, "NameEnum");
39+
Assert.assertEquals(enumVar.name, "name");
40+
Assert.assertEquals(enumVar.defaultValue, "null");
41+
Assert.assertEquals(enumVar.baseType, "String");
42+
Assert.assertTrue(enumVar.isEnum);
43+
}
44+
45+
@Test(description = "not override identical parent enums")
46+
public void overrideEnumTest() {
47+
final StringProperty identicalEnumProperty = new StringProperty();
48+
identicalEnumProperty.setEnum(Arrays.asList("VALUE1", "VALUE2", "VALUE3"));
49+
50+
final StringProperty subEnumProperty = new StringProperty();
51+
subEnumProperty.setEnum(Arrays.asList("SUB1", "SUB2", "SUB3"));
52+
53+
// Add one enum property to the parent
54+
final Map<String, Property> parentProperties = new HashMap<String, Property>();
55+
parentProperties.put("sharedThing", identicalEnumProperty);
56+
57+
// Add TWO enums to the subType model; one of which is identical to the one in parent class
58+
final Map<String, Property> subProperties = new HashMap<String, Property>();
59+
subProperties.put("sharedThing", identicalEnumProperty);
60+
subProperties.put("unsharedThing", identicalEnumProperty);
61+
62+
final ModelImpl parentModel = new ModelImpl();
63+
parentModel.setProperties(parentProperties);
64+
parentModel.name("parentModel");
65+
66+
final ModelImpl subModel = new ModelImpl();
67+
subModel.setProperties(subProperties);
68+
subModel.name("subModel");
69+
70+
final ComposedModel model = new ComposedModel()
71+
.parent(new RefModel(parentModel.getName()))
72+
.child(subModel)
73+
.interfaces(new ArrayList<RefModel>());
74+
75+
final DefaultCodegen codegen = new DartClientCodegen();
76+
final Map<String, Model> allModels = new HashMap<String, Model>();
77+
allModels.put(parentModel.getName(), parentModel);
78+
allModels.put(subModel.getName(), subModel);
79+
80+
final CodegenModel cm = codegen.fromModel("sample", model, allModels);
81+
82+
Assert.assertEquals(cm.name, "sample");
83+
Assert.assertEquals(cm.classname, "Sample");
84+
Assert.assertEquals(cm.parent, "ParentModel");
85+
Assert.assertTrue(cm.imports.contains("ParentModel"));
86+
87+
Assert.assertEquals(cm.vars.size(), 2);
88+
System.out.println(cm.vars);
89+
CodegenProperty enumVar = cm.vars.get(0);
90+
Assert.assertEquals(enumVar.baseName, "sharedThing");
91+
Assert.assertEquals(enumVar.datatype, "String");
92+
Assert.assertEquals(enumVar.datatypeWithEnum, "SharedThingEnum");
93+
Assert.assertTrue(enumVar.isEnum);
94+
enumVar = cm.vars.get(1);
95+
Assert.assertEquals(enumVar.baseName, "unsharedThing");
96+
Assert.assertEquals(enumVar.datatype, "String");
97+
Assert.assertEquals(enumVar.datatypeWithEnum, "UnsharedThingEnum");
98+
Assert.assertTrue(enumVar.isEnum);
99+
}
100+
}

samples/client/petstore/dart/flutter_petstore/swagger/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,10 @@ Class | Method | HTTP request | Description
8787

8888
## Documentation For Models
8989

90+
- [Amount](docs//Amount.md)
9091
- [ApiResponse](docs//ApiResponse.md)
9192
- [Category](docs//Category.md)
93+
- [Currency](docs//Currency.md)
9294
- [Order](docs//Order.md)
9395
- [Pet](docs//Pet.md)
9496
- [Tag](docs//Tag.md)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# swagger.model.Amount
2+
3+
## Load the model package
4+
```dart
5+
import 'package:swagger/api.dart';
6+
```
7+
8+
## Properties
9+
Name | Type | Description | Notes
10+
------------ | ------------- | ------------- | -------------
11+
**value** | **double** | some description | [default to null]
12+
**currency** | [**Currency**](Currency.md) | | [default to null]
13+
14+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
15+
16+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# swagger.model.Currency
2+
3+
## Load the model package
4+
```dart
5+
import 'package:swagger/api.dart';
6+
```
7+
8+
## Properties
9+
Name | Type | Description | Notes
10+
------------ | ------------- | ------------- | -------------
11+
12+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
13+
14+

samples/client/petstore/dart/flutter_petstore/swagger/lib/api.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
library swagger.api;
22

3-
import 'dart:convert';
43
import 'dart:async';
4+
import 'dart:convert';
55
import 'package:http/http.dart';
66

77
part 'api_client.dart';
@@ -16,8 +16,10 @@ part 'api/pet_api.dart';
1616
part 'api/store_api.dart';
1717
part 'api/user_api.dart';
1818

19+
part 'model/amount.dart';
1920
part 'model/api_response.dart';
2021
part 'model/category.dart';
22+
part 'model/currency.dart';
2123
part 'model/order.dart';
2224
part 'model/pet.dart';
2325
part 'model/tag.dart';

samples/client/petstore/dart/flutter_petstore/swagger/lib/api_client.dart

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,14 @@ class ApiClient {
3939
return value is bool ? value : '$value'.toLowerCase() == 'true';
4040
case 'double':
4141
return value is double ? value : double.parse('$value');
42+
case 'Amount':
43+
return new Amount.fromJson(value);
4244
case 'ApiResponse':
4345
return new ApiResponse.fromJson(value);
4446
case 'Category':
4547
return new Category.fromJson(value);
48+
case 'Currency':
49+
return new Currency.fromJson(value);
4650
case 'Order':
4751
return new Order.fromJson(value);
4852
case 'Pet':
@@ -72,13 +76,13 @@ class ApiClient {
7276
throw new ApiException(500, 'Could not find a suitable class for deserialization');
7377
}
7478

75-
dynamic deserialize(String jsonStr, String targetType) {
79+
dynamic deserialize(String jsonVal, String targetType) {
7680
// Remove all spaces. Necessary for reg expressions as well.
7781
targetType = targetType.replaceAll(' ', '');
7882

79-
if (targetType == 'String') return jsonStr;
83+
if (targetType == 'String') return jsonVal;
8084

81-
var decodedJson = json.decode(jsonStr);
85+
var decodedJson = json.decode(jsonVal);
8286
return _deserialize(decodedJson, targetType);
8387
}
8488

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
part of swagger.api;
2+
3+
class Amount {
4+
/* some description */
5+
double value = null;
6+
// range from 0.01 to 1000000000000000//
7+
8+
Currency currency = null;
9+
10+
Amount();
11+
12+
@override
13+
String toString() {
14+
return 'Amount[value=$value, currency=$currency, ]';
15+
}
16+
17+
Amount.fromJson(Map<String, dynamic> json) {
18+
if (json == null) return;
19+
value =
20+
json['value']
21+
;
22+
currency =
23+
24+
25+
new Currency.fromJson(json['currency'])
26+
;
27+
}
28+
29+
Map<String, dynamic> toJson() {
30+
return {
31+
'value': value,
32+
'currency': currency
33+
};
34+
}
35+
36+
static List<Amount> listFromJson(List<dynamic> json) {
37+
return json == null ? new List<Amount>() : json.map((value) => new Amount.fromJson(value)).toList();
38+
}
39+
40+
static Map<String, Amount> mapFromJson(Map<String, Map<String, dynamic>> json) {
41+
var map = new Map<String, Amount>();
42+
if (json != null && json.length > 0) {
43+
json.forEach((String key, Map<String, dynamic> value) => map[key] = new Amount.fromJson(value));
44+
}
45+
return map;
46+
}
47+
}
48+

0 commit comments

Comments
 (0)