Skip to content
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

[dart] Fix api client deserialization for json_serializable #8882

46 changes: 36 additions & 10 deletions modules/openapi-generator/src/main/resources/dart2/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class {{{classname}}} {
{{/allParams}}

{{/hasParams}}
final path = '{{{path}}}'{{#pathParams}}
final path = r'{{{path}}}'{{#pathParams}}
.replaceAll('{' + '{{{baseName}}}' + '}', {{{paramName}}}.toString()){{/pathParams}};

Object postBody{{#bodyParam}} = {{{paramName}}}{{/bodyParam}};
Expand Down Expand Up @@ -185,21 +185,47 @@ class {{{classname}}} {
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
// FormatException when trying to decode an empty string.
if (response.body != null && response.statusCode != HttpStatus.noContent) {
{{#isArray}}
{{#native_serialization}}
{{#isArray}}
agilob marked this conversation as resolved.
Show resolved Hide resolved
return (apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as List)
.cast<{{{returnBaseType}}}>()
.{{#uniqueItems}}toSet(){{/uniqueItems}}{{^uniqueItems}}toList(growable: false){{/uniqueItems}};
{{/isArray}}
{{^isArray}}
{{#isMap}}
{{/isArray}}
{{^isArray}}
{{#isMap}}
return {{{returnType}}}.from(apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}'));
{{/isMap}}
{{^isMap}}
{{/isMap}}
{{^isMap}}
return apiClient.deserialize(_decodeBodyBytes(response), '{{{returnType}}}') as {{{returnType}}};
{{/isMap}}
{{/isArray}}
{{/isMap}}{{/isArray}}{{/native_serialization}}{{#json_serializable}}
{{#isArray}}
{{#uniqueItems}}
return (json.decode(response.body) as List)
.map((i) => {{{returnBaseType}}}.fromJson(i))
.toSet();
{{/uniqueItems}}
{{^uniqueItems}}
return (json.decode(response.body) as List)
.map((i) => {{{returnBaseType}}}.fromJson(i))
.toList();
{{/uniqueItems}}
{{/isArray}}
{{^isArray}}
{{#isMap}}
return {{{returnType}}}.from(json.decode(response.body));
{{/isMap}}
{{^isMap}}
{{#returnTypeIsPrimitive}}
return response.body as {{{returnBaseType}}};
{{/returnTypeIsPrimitive}}
{{^returnTypeIsPrimitive}}
return {{{returnType}}}.fromJson(json.decode(response.body));
{{/returnTypeIsPrimitive}}
{{/isMap}}
{{/isArray}}
{{/json_serializable}}
}
return null;
return Future.value(null);
{{/returnType}}
}
{{/operation}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,6 @@ class ApiClient {
Map<String, Authentication> get authentications =>
Map.unmodifiable(_authentications);

dynamic deserialize(String json, String targetType, {bool growable}) {
// Remove all spaces. Necessary for reg expressions as well.
targetType = targetType.replaceAll(' ', '');

return targetType == 'String'
? json
: _deserialize(jsonDecode(json), targetType, growable: true == growable);
}

String serialize(Object obj) => obj == null ? '' : json.encode(obj);

T getAuthentication<T extends Authentication>(String name) {
final authentication = _authentications[name];
return authentication is T ? authentication : null;
Expand Down Expand Up @@ -159,6 +148,7 @@ class ApiClient {
throw ApiException(HttpStatus.badRequest, 'Invalid HTTP operation: $method $path',);
}

{{#native_serialization}}
dynamic _deserialize(dynamic value, String targetType, {bool growable}) {
try {
switch (targetType) {
Expand Down Expand Up @@ -216,6 +206,18 @@ class ApiClient {
throw ApiException(HttpStatus.internalServerError, 'Could not find a suitable class for deserialization',);
}

dynamic deserialize(String json, String targetType, {bool growable}) {
// Remove all spaces. Necessary for reg expressions as well.
targetType = targetType.replaceAll(' ', '');

return targetType == 'String'
? json
: _deserialize(jsonDecode(json), targetType, growable: true == growable);
}
{{/native_serialization}}

String serialize(Object obj) => obj == null ? '' : json.encode(obj);

/// Update query and header parameters based on authentication settings.
/// @param authNames The authentications to apply
void _updateParamsForAuth(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ String parameterToString(dynamic value) {
{{#model}}
{{#isEnum}}
if (value is {{{classname}}}) {
{{#native_serialization}} return {{{classname}}}TypeTransformer().encode(value).toString();{{/native_serialization}}
{{#json_serializable}} return _${{{classname}}}EnumMap[value];{{/json_serializable}}
{{#native_serialization}} return {{{classname}}}TypeTransformer().encode(value).toString();{{/native_serialization}}{{#json_serializable}} return value.toString();{{/json_serializable}}
}
{{/isEnum}}
{{/model}}
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1353,6 +1353,7 @@
<module>samples/client/petstore/dart2/petstore</module>
<module>samples/openapi3/client/petstore/dart2/petstore_client_lib</module>
<module>samples/openapi3/client/petstore/dart2/petstore</module>
<module>samples/openapi3/client/petstore/dart2/petstore_json_serializable_client_lib_fake</module>
<module>samples/client/petstore/dart-dio/petstore_client_lib</module>
<module>samples/openapi3/client/petstore/dart-dio/petstore_client_lib</module>
<module>samples/openapi3/client/petstore/dart-dio/petstore_client_lib_fake</module>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ No authorization required
- **Content-Type**: application/json
- **Accept**: */*


### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class PetApi {
throw ApiException(HttpStatus.badRequest, 'Missing required param: body');
}

final path = '/pet';
final path = r'/pet';

Object postBody = body;

Expand Down Expand Up @@ -94,7 +94,7 @@ class PetApi {
throw ApiException(HttpStatus.badRequest, 'Missing required param: petId');
}

final path = '/pet/{petId}'
final path = r'/pet/{petId}'
.replaceAll('{' + 'petId' + '}', petId.toString());

Object postBody;
Expand Down Expand Up @@ -166,7 +166,7 @@ class PetApi {
throw ApiException(HttpStatus.badRequest, 'Missing required param: status');
}

final path = '/pet/findByStatus';
final path = r'/pet/findByStatus';

Object postBody;

Expand Down Expand Up @@ -225,7 +225,7 @@ class PetApi {
.cast<Pet>()
.toList(growable: false);
}
return null;
return Future.value(null);
}

/// Finds Pets by tags
Expand All @@ -244,7 +244,7 @@ class PetApi {
throw ApiException(HttpStatus.badRequest, 'Missing required param: tags');
}

final path = '/pet/findByTags';
final path = r'/pet/findByTags';

Object postBody;

Expand Down Expand Up @@ -303,7 +303,7 @@ class PetApi {
.cast<Pet>()
.toList(growable: false);
}
return null;
return Future.value(null);
}

/// Find pet by ID
Expand All @@ -322,7 +322,7 @@ class PetApi {
throw ApiException(HttpStatus.badRequest, 'Missing required param: petId');
}

final path = '/pet/{petId}'
final path = r'/pet/{petId}'
.replaceAll('{' + 'petId' + '}', petId.toString());

Object postBody;
Expand Down Expand Up @@ -377,8 +377,8 @@ class PetApi {
// FormatException when trying to decode an empty string.
if (response.body != null && response.statusCode != HttpStatus.noContent) {
return apiClient.deserialize(_decodeBodyBytes(response), 'Pet') as Pet;
}
return null;
}
return Future.value(null);
}

/// Update an existing pet
Expand All @@ -395,7 +395,7 @@ class PetApi {
throw ApiException(HttpStatus.badRequest, 'Missing required param: body');
}

final path = '/pet';
final path = r'/pet';

Object postBody = body;

Expand Down Expand Up @@ -464,7 +464,7 @@ class PetApi {
throw ApiException(HttpStatus.badRequest, 'Missing required param: petId');
}

final path = '/pet/{petId}'
final path = r'/pet/{petId}'
.replaceAll('{' + 'petId' + '}', petId.toString());

Object postBody;
Expand Down Expand Up @@ -554,7 +554,7 @@ class PetApi {
throw ApiException(HttpStatus.badRequest, 'Missing required param: petId');
}

final path = '/pet/{petId}/uploadImage'
final path = r'/pet/{petId}/uploadImage'
.replaceAll('{' + 'petId' + '}', petId.toString());

Object postBody;
Expand Down Expand Up @@ -625,7 +625,7 @@ class PetApi {
// FormatException when trying to decode an empty string.
if (response.body != null && response.statusCode != HttpStatus.noContent) {
return apiClient.deserialize(_decodeBodyBytes(response), 'ApiResponse') as ApiResponse;
}
return null;
}
return Future.value(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class StoreApi {
throw ApiException(HttpStatus.badRequest, 'Missing required param: orderId');
}

final path = '/store/order/{orderId}'
final path = r'/store/order/{orderId}'
.replaceAll('{' + 'orderId' + '}', orderId.toString());

Object postBody;
Expand Down Expand Up @@ -89,7 +89,7 @@ class StoreApi {
///
/// Note: This method returns the HTTP [Response].
Future<Response> getInventoryWithHttpInfo() async {
final path = '/store/inventory';
final path = r'/store/inventory';

Object postBody;

Expand Down Expand Up @@ -139,7 +139,7 @@ class StoreApi {
if (response.body != null && response.statusCode != HttpStatus.noContent) {
return Map<String, int>.from(apiClient.deserialize(_decodeBodyBytes(response), 'Map<String, int>'));
}
return null;
return Future.value(null);
}

/// Find purchase order by ID
Expand All @@ -158,7 +158,7 @@ class StoreApi {
throw ApiException(HttpStatus.badRequest, 'Missing required param: orderId');
}

final path = '/store/order/{orderId}'
final path = r'/store/order/{orderId}'
.replaceAll('{' + 'orderId' + '}', orderId.toString());

Object postBody;
Expand Down Expand Up @@ -213,8 +213,8 @@ class StoreApi {
// FormatException when trying to decode an empty string.
if (response.body != null && response.statusCode != HttpStatus.noContent) {
return apiClient.deserialize(_decodeBodyBytes(response), 'Order') as Order;
}
return null;
}
return Future.value(null);
}

/// Place an order for a pet
Expand All @@ -231,7 +231,7 @@ class StoreApi {
throw ApiException(HttpStatus.badRequest, 'Missing required param: body');
}

final path = '/store/order';
final path = r'/store/order';

Object postBody = body;

Expand Down Expand Up @@ -283,7 +283,7 @@ class StoreApi {
// FormatException when trying to decode an empty string.
if (response.body != null && response.statusCode != HttpStatus.noContent) {
return apiClient.deserialize(_decodeBodyBytes(response), 'Order') as Order;
}
return null;
}
return Future.value(null);
}
}
Loading