From fdbf02764d144ff1469ce3905dff5b19352b6447 Mon Sep 17 00:00:00 2001 From: Peter Leibiger Date: Mon, 7 Jun 2021 03:49:59 +0200 Subject: [PATCH] [dart][dart-dio] Add support for query collection parameter format (#9635) * [dart][dart-dio] Add support for query collection parameter format * add support for collectionFormat in query parameters and www-url-encoded content * add tests * remove empty query parameter maps from generated code * closes #6681 * closes #9522 * closes #8271 (the last remaining parts) * Fix formatting --- .../languages/DartDioNextClientCodegen.java | 4 +- .../resources/dart/libraries/dio/api.mustache | 18 ++- .../dart/libraries/dio/api_util.mustache | 28 ---- .../built_value/api_util.mustache | 75 +++++++++++ .../built_value/query_param.mustache | 1 + .../built_value/serialize.mustache | 13 +- .../lib/src/api/another_fake_api.dart | 5 - .../lib/src/api/default_api.dart | 4 - .../lib/src/api/fake_api.dart | 125 +++++------------- .../src/api/fake_classname_tags123_api.dart | 5 - .../lib/src/api/pet_api.dart | 41 +----- .../lib/src/api/store_api.dart | 17 --- .../lib/src/api/user_api.dart | 37 +----- .../lib/src/api_util.dart | 49 ++++++- .../test/api/fake_api_test.dart | 21 ++- .../test/api/pet_api_test.dart | 12 +- .../test/matcher/list_param_matcher.dart | 20 +++ 17 files changed, 233 insertions(+), 242 deletions(-) delete mode 100644 modules/openapi-generator/src/main/resources/dart/libraries/dio/api_util.mustache create mode 100644 modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api_util.mustache create mode 100644 modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/query_param.mustache create mode 100644 samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake_tests/test/matcher/list_param_matcher.dart diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioNextClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioNextClientCodegen.java index 6b7beaeaea2e..6557d7cad3e7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioNextClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioNextClientCodegen.java @@ -153,7 +153,6 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen { final String srcFolder = libFolder + File.separator + "src"; supportingFiles.add(new SupportingFile("api_client.mustache", srcFolder, "api.dart")); - supportingFiles.add(new SupportingFile("api_util.mustache", srcFolder, "api_util.dart")); final String authFolder = srcFolder + File.separator + "auth"; supportingFiles.add(new SupportingFile("auth/api_key_auth.mustache", authFolder, "api_key_auth.dart")); @@ -177,6 +176,7 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen { private void configureSerializationLibraryBuiltValue(String srcFolder) { supportingFiles.add(new SupportingFile("serialization/built_value/serializers.mustache", srcFolder, "serializers.dart")); + supportingFiles.add(new SupportingFile("serialization/built_value/api_util.mustache", srcFolder, "api_util.dart")); typeMapping.put("Array", "BuiltList"); typeMapping.put("array", "BuiltList"); @@ -339,7 +339,7 @@ public class DartDioNextClientCodegen extends AbstractDartCodegen { } resultImports.addAll(rewriteImports(op.imports, false)); - if (op.getHasFormParams()) { + if (op.getHasFormParams() || op.getHasQueryParams()) { resultImports.add("package:" + pubName + "/src/api_util.dart"); } diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache index 5182266d24b9..cdfe8be4dd8f 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache @@ -83,14 +83,13 @@ class {{classname}} { },{{#hasConsumes}} contentType: '{{#prioritizedContentTypes}}{{#-first}}{{{mediaType}}}{{/-first}}{{/prioritizedContentTypes}}',{{/hasConsumes}} validateStatus: validateStatus, - ); + );{{#hasQueryParams}} final _queryParameters = { {{#queryParams}} - {{^required}}{{^isNullable}}if ({{{paramName}}} != null) {{/isNullable}}{{/required}}r'{{baseName}}': {{paramName}}, + {{^required}}{{^isNullable}}if ({{{paramName}}} != null) {{/isNullable}}{{/required}}r'{{baseName}}': {{#useBuiltValue}}{{>serialization/built_value/query_param}}{{/useBuiltValue}}, {{/queryParams}} - }; - {{#hasBodyOrFormParams}} + };{{/hasQueryParams}}{{#hasBodyOrFormParams}} dynamic _bodyData; @@ -100,20 +99,19 @@ class {{classname}} { throw DioError( requestOptions: _options.compose( _dio.options, - _path, - queryParameters: _queryParameters, + _path,{{#hasQueryParams}} + queryParameters: _queryParameters,{{/hasQueryParams}} ), type: DioErrorType.other, error: error, )..stackTrace = stackTrace; - } - {{/hasBodyOrFormParams}} + }{{/hasBodyOrFormParams}} final _response = await _dio.request( _path,{{#hasBodyOrFormParams}} data: _bodyData,{{/hasBodyOrFormParams}} - options: _options, - queryParameters: _queryParameters, + options: _options,{{#hasQueryParams}} + queryParameters: _queryParameters,{{/hasQueryParams}} cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api_util.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/api_util.mustache deleted file mode 100644 index 4cdc6bcea3c5..000000000000 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api_util.mustache +++ /dev/null @@ -1,28 +0,0 @@ -{{>header}} -import 'dart:convert'; - -import 'package:built_collection/built_collection.dart'; -import 'package:built_value/serializer.dart'; - -/// Format the given form parameter object into something that Dio can handle. -/// Returns primitive or String. -/// Returns List/Map if the value is BuildList/BuiltMap. -dynamic encodeFormParameter(Serializers serializers, dynamic value, FullType type) { - if (value == null) { - return ''; - } - if (value is String || value is num || value is bool) { - return value; - } - final serialized = serializers.serialize( - value as Object, - specifiedType: type, - ); - if (serialized is String) { - return serialized; - } - if (value is BuiltList || value is BuiltMap) { - return serialized; - } - return json.encode(serialized); -} diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api_util.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api_util.mustache new file mode 100644 index 000000000000..fb5ab08aeda0 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/api_util.mustache @@ -0,0 +1,75 @@ +{{>header}} +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:built_collection/built_collection.dart'; +import 'package:built_value/serializer.dart'; +import 'package:dio/dio.dart'; +import 'package:dio/src/parameter.dart'; + +/// Format the given form parameter object into something that Dio can handle. +/// Returns primitive or String. +/// Returns List/Map if the value is BuildList/BuiltMap. +dynamic encodeFormParameter(Serializers serializers, dynamic value, FullType type) { + if (value == null) { + return ''; + } + if (value is String || value is num || value is bool) { + return value; + } + final serialized = serializers.serialize( + value as Object, + specifiedType: type, + ); + if (serialized is String) { + return serialized; + } + if (value is BuiltList || value is BuiltSet || value is BuiltMap) { + return serialized; + } + return json.encode(serialized); +} + +dynamic encodeQueryParameter( + Serializers serializers, + dynamic value, + FullType type, +) { + if (value == null) { + return ''; + } + if (value is String || value is num || value is bool) { + return value; + } + if (value is Uint8List) { + // Currently not sure how to serialize this + return value; + } + final serialized = serializers.serialize( + value as Object, + specifiedType: type, + ); + if (serialized == null) { + return ''; + } + if (serialized is String) { + return serialized; + } + return serialized; +} + +ListParam encodeCollectionQueryParameter( + Serializers serializers, + dynamic value, + FullType type, { + ListFormat format = ListFormat.multi, +}) { + final serialized = serializers.serialize( + value as Object, + specifiedType: type, + ); + if (value is BuiltList || value is BuiltSet) { + return ListParam(List.of((serialized as Iterable).cast()), format); + } + throw ArgumentError('Invalid value passed to encodeCollectionQueryParameter'); +} diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/query_param.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/query_param.mustache new file mode 100644 index 000000000000..3a27e77225e2 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/query_param.mustache @@ -0,0 +1 @@ +{{#isContainer}}encodeCollectionQueryParameter<{{{baseType}}}>{{/isContainer}}{{^isContainer}}encodeQueryParameter{{/isContainer}}(_serializers, {{{paramName}}}, const FullType({{^isContainer}}{{{dataType}}}){{/isContainer}}{{#isContainer}}Built{{#isMap}}Map{{/isMap}}{{#isArray}}{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}{{/isArray}}, [{{#isMap}}FullType(String), {{/isMap}}FullType({{{baseType}}})]), format: ListFormat.{{collectionFormat}}{{/isContainer}}) \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/serialize.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/serialize.mustache index 03d38c93878d..60dcd1773ba0 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/serialize.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/serialize.mustache @@ -1,9 +1,18 @@ {{#hasFormParams}} - _bodyData = {{#isMultipart}}FormData.fromMap({{/isMultipart}}{ + {{#isMultipart}} + _bodyData = FormData.fromMap({ {{#formParams}} {{^required}}{{^isNullable}}if ({{{paramName}}} != null) {{/isNullable}}{{/required}}r'{{{baseName}}}': {{#isFile}}{{{paramName}}}{{/isFile}}{{^isFile}}encodeFormParameter(_serializers, {{{paramName}}}, const FullType({{^isContainer}}{{{baseType}}}{{/isContainer}}{{#isContainer}}Built{{#isMap}}Map{{/isMap}}{{#isArray}}{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}{{/isArray}}, [{{#isMap}}FullType(String), {{/isMap}}FullType({{{baseType}}})]{{/isContainer}})){{/isFile}}, {{/formParams}} - }{{#isMultipart}}){{/isMultipart}}; + }); + {{/isMultipart}} + {{^isMultipart}} + _bodyData = { + {{#formParams}} + {{^required}}{{^isNullable}}if ({{{paramName}}} != null) {{/isNullable}}{{/required}}r'{{{baseName}}}': {{>serialization/built_value/query_param}}, + {{/formParams}} + }; + {{/isMultipart}} {{/hasFormParams}} {{#bodyParam}} {{#isPrimitiveType}} diff --git a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/another_fake_api.dart b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/another_fake_api.dart index 4d0e1366d063..45709153344b 100644 --- a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/another_fake_api.dart +++ b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/another_fake_api.dart @@ -54,9 +54,6 @@ class AnotherFakeApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -68,7 +65,6 @@ class AnotherFakeApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -79,7 +75,6 @@ class AnotherFakeApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, diff --git a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/default_api.dart b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/default_api.dart index 3a46c9a2048e..7ad2d45db758 100644 --- a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/default_api.dart +++ b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/default_api.dart @@ -51,13 +51,9 @@ class DefaultApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - final _response = await _dio.request( _path, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, diff --git a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/fake_api.dart b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/fake_api.dart index 20e4483e544b..fbc60334177c 100644 --- a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/fake_api.dart +++ b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/fake_api.dart @@ -61,13 +61,9 @@ class FakeApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - final _response = await _dio.request( _path, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -151,7 +147,7 @@ class FakeApi { ); final _queryParameters = { - if (query1 != null) r'query_1': query1, + if (query1 != null) r'query_1': encodeQueryParameter(_serializers, query1, const FullType(String)), }; dynamic _bodyData; @@ -222,9 +218,6 @@ class FakeApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -235,7 +228,6 @@ class FakeApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -246,7 +238,6 @@ class FakeApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -315,9 +306,6 @@ class FakeApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -329,7 +317,6 @@ class FakeApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -340,7 +327,6 @@ class FakeApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -413,9 +399,6 @@ class FakeApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -426,7 +409,6 @@ class FakeApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -437,7 +419,6 @@ class FakeApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -506,9 +487,6 @@ class FakeApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -519,7 +497,6 @@ class FakeApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -530,7 +507,6 @@ class FakeApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -599,9 +575,6 @@ class FakeApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -613,7 +586,6 @@ class FakeApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -624,7 +596,6 @@ class FakeApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -697,9 +668,6 @@ class FakeApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -710,7 +678,6 @@ class FakeApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -721,7 +688,6 @@ class FakeApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -767,9 +733,6 @@ class FakeApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -781,7 +744,6 @@ class FakeApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -792,7 +754,6 @@ class FakeApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -841,7 +802,7 @@ class FakeApi { ); final _queryParameters = { - r'query': query, + r'query': encodeQueryParameter(_serializers, query, const FullType(String)), }; dynamic _bodyData; @@ -912,9 +873,6 @@ class FakeApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -926,7 +884,6 @@ class FakeApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -937,7 +894,6 @@ class FakeApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -1041,27 +997,24 @@ class FakeApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { _bodyData = { - if (integer != null) r'integer': encodeFormParameter(_serializers, integer, const FullType(int)), - if (int32 != null) r'int32': encodeFormParameter(_serializers, int32, const FullType(int)), - if (int64 != null) r'int64': encodeFormParameter(_serializers, int64, const FullType(int)), - r'number': encodeFormParameter(_serializers, number, const FullType(num)), - if (float != null) r'float': encodeFormParameter(_serializers, float, const FullType(double)), - r'double': encodeFormParameter(_serializers, double_, const FullType(double)), - if (string != null) r'string': encodeFormParameter(_serializers, string, const FullType(String)), - r'pattern_without_delimiter': encodeFormParameter(_serializers, patternWithoutDelimiter, const FullType(String)), - r'byte': encodeFormParameter(_serializers, byte, const FullType(String)), - if (binary != null) r'binary': binary, - if (date != null) r'date': encodeFormParameter(_serializers, date, const FullType(Date)), - if (dateTime != null) r'dateTime': encodeFormParameter(_serializers, dateTime, const FullType(DateTime)), - if (password != null) r'password': encodeFormParameter(_serializers, password, const FullType(String)), - if (callback != null) r'callback': encodeFormParameter(_serializers, callback, const FullType(String)), + if (integer != null) r'integer': encodeQueryParameter(_serializers, integer, const FullType(int)), + if (int32 != null) r'int32': encodeQueryParameter(_serializers, int32, const FullType(int)), + if (int64 != null) r'int64': encodeQueryParameter(_serializers, int64, const FullType(int)), + r'number': encodeQueryParameter(_serializers, number, const FullType(num)), + if (float != null) r'float': encodeQueryParameter(_serializers, float, const FullType(double)), + r'double': encodeQueryParameter(_serializers, double_, const FullType(double)), + if (string != null) r'string': encodeQueryParameter(_serializers, string, const FullType(String)), + r'pattern_without_delimiter': encodeQueryParameter(_serializers, patternWithoutDelimiter, const FullType(String)), + r'byte': encodeQueryParameter(_serializers, byte, const FullType(String)), + if (binary != null) r'binary': encodeQueryParameter(_serializers, binary, const FullType(Uint8List)), + if (date != null) r'date': encodeQueryParameter(_serializers, date, const FullType(Date)), + if (dateTime != null) r'dateTime': encodeQueryParameter(_serializers, dateTime, const FullType(DateTime)), + if (password != null) r'password': encodeQueryParameter(_serializers, password, const FullType(String)), + if (callback != null) r'callback': encodeQueryParameter(_serializers, callback, const FullType(String)), }; } catch(error, stackTrace) { @@ -1069,7 +1022,6 @@ class FakeApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -1080,7 +1032,6 @@ class FakeApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -1143,18 +1094,18 @@ class FakeApi { ); final _queryParameters = { - if (enumQueryStringArray != null) r'enum_query_string_array': enumQueryStringArray, - if (enumQueryString != null) r'enum_query_string': enumQueryString, - if (enumQueryInteger != null) r'enum_query_integer': enumQueryInteger, - if (enumQueryDouble != null) r'enum_query_double': enumQueryDouble, + if (enumQueryStringArray != null) r'enum_query_string_array': encodeCollectionQueryParameter(_serializers, enumQueryStringArray, const FullType(BuiltList, [FullType(String)]), format: ListFormat.multi), + if (enumQueryString != null) r'enum_query_string': encodeQueryParameter(_serializers, enumQueryString, const FullType(String)), + if (enumQueryInteger != null) r'enum_query_integer': encodeQueryParameter(_serializers, enumQueryInteger, const FullType(int)), + if (enumQueryDouble != null) r'enum_query_double': encodeQueryParameter(_serializers, enumQueryDouble, const FullType(double)), }; dynamic _bodyData; try { _bodyData = { - if (enumFormStringArray != null) r'enum_form_string_array': encodeFormParameter(_serializers, enumFormStringArray, const FullType(BuiltList, [FullType(String)])), - if (enumFormString != null) r'enum_form_string': encodeFormParameter(_serializers, enumFormString, const FullType(String)), + if (enumFormStringArray != null) r'enum_form_string_array': encodeCollectionQueryParameter(_serializers, enumFormStringArray, const FullType(BuiltList, [FullType(String)]), format: ListFormat.csv), + if (enumFormString != null) r'enum_form_string': encodeQueryParameter(_serializers, enumFormString, const FullType(String)), }; } catch(error, stackTrace) { @@ -1236,10 +1187,10 @@ class FakeApi { ); final _queryParameters = { - r'required_string_group': requiredStringGroup, - r'required_int64_group': requiredInt64Group, - if (stringGroup != null) r'string_group': stringGroup, - if (int64Group != null) r'int64_group': int64Group, + r'required_string_group': encodeQueryParameter(_serializers, requiredStringGroup, const FullType(int)), + r'required_int64_group': encodeQueryParameter(_serializers, requiredInt64Group, const FullType(int)), + if (stringGroup != null) r'string_group': encodeQueryParameter(_serializers, stringGroup, const FullType(int)), + if (int64Group != null) r'int64_group': encodeQueryParameter(_serializers, int64Group, const FullType(int)), }; final _response = await _dio.request( @@ -1291,9 +1242,6 @@ class FakeApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -1305,7 +1253,6 @@ class FakeApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -1316,7 +1263,6 @@ class FakeApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -1364,15 +1310,12 @@ class FakeApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { _bodyData = { - r'param': encodeFormParameter(_serializers, param, const FullType(String)), - r'param2': encodeFormParameter(_serializers, param2, const FullType(String)), + r'param': encodeQueryParameter(_serializers, param, const FullType(String)), + r'param2': encodeQueryParameter(_serializers, param2, const FullType(String)), }; } catch(error, stackTrace) { @@ -1380,7 +1323,6 @@ class FakeApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -1391,7 +1333,6 @@ class FakeApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -1445,11 +1386,11 @@ class FakeApi { ); final _queryParameters = { - r'pipe': pipe, - r'ioutil': ioutil, - r'http': http, - r'url': url, - r'context': context, + r'pipe': encodeCollectionQueryParameter(_serializers, pipe, const FullType(BuiltList, [FullType(String)]), format: ListFormat.pipes), + r'ioutil': encodeCollectionQueryParameter(_serializers, ioutil, const FullType(BuiltList, [FullType(String)]), format: ListFormat.csv), + r'http': encodeCollectionQueryParameter(_serializers, http, const FullType(BuiltList, [FullType(String)]), format: ListFormat.ssv), + r'url': encodeCollectionQueryParameter(_serializers, url, const FullType(BuiltList, [FullType(String)]), format: ListFormat.csv), + r'context': encodeCollectionQueryParameter(_serializers, context, const FullType(BuiltList, [FullType(String)]), format: ListFormat.multi), }; final _response = await _dio.request( diff --git a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/fake_classname_tags123_api.dart b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/fake_classname_tags123_api.dart index e48c38c96ba6..96329ea11f23 100644 --- a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/fake_classname_tags123_api.dart +++ b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/fake_classname_tags123_api.dart @@ -61,9 +61,6 @@ class FakeClassnameTags123Api { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -75,7 +72,6 @@ class FakeClassnameTags123Api { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -86,7 +82,6 @@ class FakeClassnameTags123Api { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, diff --git a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/pet_api.dart b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/pet_api.dart index be1d9d27924d..1dedc0456eb2 100644 --- a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/pet_api.dart +++ b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/pet_api.dart @@ -62,9 +62,6 @@ class PetApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -76,7 +73,6 @@ class PetApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -87,7 +83,6 @@ class PetApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -140,13 +135,9 @@ class PetApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - final _response = await _dio.request( _path, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -197,7 +188,7 @@ class PetApi { ); final _queryParameters = { - r'status': status, + r'status': encodeCollectionQueryParameter(_serializers, status, const FullType(BuiltList, [FullType(String)]), format: ListFormat.csv), }; final _response = await _dio.request( @@ -282,7 +273,7 @@ class PetApi { ); final _queryParameters = { - r'tags': tags, + r'tags': encodeCollectionQueryParameter(_serializers, tags, const FullType(BuiltSet, [FullType(String)]), format: ListFormat.csv), }; final _response = await _dio.request( @@ -367,13 +358,9 @@ class PetApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - final _response = await _dio.request( _path, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -451,9 +438,6 @@ class PetApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -465,7 +449,6 @@ class PetApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -476,7 +459,6 @@ class PetApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -531,15 +513,12 @@ class PetApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { _bodyData = { - if (name != null) r'name': encodeFormParameter(_serializers, name, const FullType(String)), - if (status != null) r'status': encodeFormParameter(_serializers, status, const FullType(String)), + if (name != null) r'name': encodeQueryParameter(_serializers, name, const FullType(String)), + if (status != null) r'status': encodeQueryParameter(_serializers, status, const FullType(String)), }; } catch(error, stackTrace) { @@ -547,7 +526,6 @@ class PetApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -558,7 +536,6 @@ class PetApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -613,9 +590,6 @@ class PetApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -629,7 +603,6 @@ class PetApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -640,7 +613,6 @@ class PetApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -722,9 +694,6 @@ class PetApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -738,7 +707,6 @@ class PetApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -749,7 +717,6 @@ class PetApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, diff --git a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/store_api.dart b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/store_api.dart index 24c4bd7a55c8..93d5ccbe97cc 100644 --- a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/store_api.dart +++ b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/store_api.dart @@ -54,13 +54,9 @@ class StoreApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - final _response = await _dio.request( _path, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -110,13 +106,9 @@ class StoreApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - final _response = await _dio.request( _path, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -188,13 +180,9 @@ class StoreApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - final _response = await _dio.request( _path, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -267,9 +255,6 @@ class StoreApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -281,7 +266,6 @@ class StoreApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -292,7 +276,6 @@ class StoreApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, diff --git a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/user_api.dart b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/user_api.dart index a05524844039..6faaed6336d1 100644 --- a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/user_api.dart +++ b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api/user_api.dart @@ -8,6 +8,7 @@ import 'package:built_value/serializer.dart'; import 'package:dio/dio.dart'; import 'package:built_collection/built_collection.dart'; +import 'package:openapi/src/api_util.dart'; import 'package:openapi/src/model/user.dart'; class UserApi { @@ -55,9 +56,6 @@ class UserApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -69,7 +67,6 @@ class UserApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -80,7 +77,6 @@ class UserApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -126,9 +122,6 @@ class UserApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -140,7 +133,6 @@ class UserApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -151,7 +143,6 @@ class UserApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -197,9 +188,6 @@ class UserApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -211,7 +199,6 @@ class UserApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -222,7 +209,6 @@ class UserApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -267,13 +253,9 @@ class UserApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - final _response = await _dio.request( _path, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -318,13 +300,9 @@ class UserApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - final _response = await _dio.request( _path, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -399,8 +377,8 @@ class UserApi { ); final _queryParameters = { - r'username': username, - r'password': password, + r'username': encodeQueryParameter(_serializers, username, const FullType(String)), + r'password': encodeQueryParameter(_serializers, password, const FullType(String)), }; final _response = await _dio.request( @@ -472,13 +450,9 @@ class UserApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - final _response = await _dio.request( _path, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, @@ -526,9 +500,6 @@ class UserApi { validateStatus: validateStatus, ); - final _queryParameters = { - }; - dynamic _bodyData; try { @@ -540,7 +511,6 @@ class UserApi { requestOptions: _options.compose( _dio.options, _path, - queryParameters: _queryParameters, ), type: DioErrorType.other, error: error, @@ -551,7 +521,6 @@ class UserApi { _path, data: _bodyData, options: _options, - queryParameters: _queryParameters, cancelToken: cancelToken, onSendProgress: onSendProgress, onReceiveProgress: onReceiveProgress, diff --git a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api_util.dart b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api_util.dart index ca7832e36930..09b9ba88fd94 100644 --- a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api_util.dart +++ b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake/lib/src/api_util.dart @@ -3,9 +3,12 @@ // import 'dart:convert'; +import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/serializer.dart'; +import 'package:dio/dio.dart'; +import 'package:dio/src/parameter.dart'; /// Format the given form parameter object into something that Dio can handle. /// Returns primitive or String. @@ -24,8 +27,52 @@ dynamic encodeFormParameter(Serializers serializers, dynamic value, FullType typ if (serialized is String) { return serialized; } - if (value is BuiltList || value is BuiltMap) { + if (value is BuiltList || value is BuiltSet || value is BuiltMap) { return serialized; } return json.encode(serialized); } + +dynamic encodeQueryParameter( + Serializers serializers, + dynamic value, + FullType type, +) { + if (value == null) { + return ''; + } + if (value is String || value is num || value is bool) { + return value; + } + if (value is Uint8List) { + // Currently not sure how to serialize this + return value; + } + final serialized = serializers.serialize( + value as Object, + specifiedType: type, + ); + if (serialized == null) { + return ''; + } + if (serialized is String) { + return serialized; + } + return serialized; +} + +ListParam encodeCollectionQueryParameter( + Serializers serializers, + dynamic value, + FullType type, { + ListFormat format = ListFormat.multi, +}) { + final serialized = serializers.serialize( + value as Object, + specifiedType: type, + ); + if (value is BuiltList || value is BuiltSet) { + return ListParam(List.of((serialized as Iterable).cast()), format); + } + throw ArgumentError('Invalid value passed to encodeCollectionQueryParameter'); +} diff --git a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake_tests/test/api/fake_api_test.dart b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake_tests/test/api/fake_api_test.dart index 9330474d4992..180815a69f1b 100644 --- a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake_tests/test/api/fake_api_test.dart +++ b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake_tests/test/api/fake_api_test.dart @@ -2,10 +2,13 @@ import 'dart:typed_data'; import 'package:built_collection/built_collection.dart'; import 'package:dio/dio.dart'; +import 'package:dio/src/parameter.dart'; import 'package:http_mock_adapter/http_mock_adapter.dart'; import 'package:openapi/openapi.dart'; import 'package:test/test.dart'; +import '../matcher/list_param_matcher.dart'; + void main() { Openapi client; DioAdapter server; @@ -97,7 +100,20 @@ void main() { (request) => request.reply(200, null), data: { 'enum_form_string': 'formString', - 'enum_form_string_array': '[foo, bar]', + 'enum_form_string_array': ListParamMatcher( + expected: ListParam( + ['foo', 'bar'], + ListFormat.csv, + ), + ), + }, + queryParameters: { + 'enum_query_string_array': ListParamMatcher( + expected: ListParam( + ['a', 'b', 'c'], + ListFormat.multi, + ), + ), }, headers: { 'content-type': 'application/x-www-form-urlencoded', @@ -105,6 +121,9 @@ void main() { ); final response = await client.getFakeApi().testEnumParameters( + enumQueryStringArray: ListBuilder( + ['a', 'b', 'c'], + ).build(), enumFormString: 'formString', enumFormStringArray: ListBuilder( ['foo', 'bar'], diff --git a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake_tests/test/api/pet_api_test.dart b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake_tests/test/api/pet_api_test.dart index 6b52fdce13ed..1ae3964851de 100644 --- a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake_tests/test/api/pet_api_test.dart +++ b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake_tests/test/api/pet_api_test.dart @@ -1,11 +1,13 @@ import 'package:built_collection/built_collection.dart'; import 'package:dio/dio.dart'; +import 'package:dio/src/parameter.dart'; import 'package:http_mock_adapter/http_mock_adapter.dart'; import 'package:http_parser/http_parser.dart'; import 'package:openapi/openapi.dart'; import 'package:test/test.dart'; import '../matcher/form_data_matcher.dart'; +import '../matcher/list_param_matcher.dart'; void main() { const photo1 = 'https://localhost/photo1.jpg'; @@ -195,10 +197,12 @@ void main() { request: Request( method: RequestMethods.get, queryParameters: { - 'status': [ - 'available', - 'sold', - ], + 'status': ListParamMatcher( + expected: ListParam( + ['available', 'sold'], + ListFormat.csv, + ), + ), }, headers: { Headers.contentTypeHeader: Matchers.pattern('application/json'), diff --git a/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake_tests/test/matcher/list_param_matcher.dart b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake_tests/test/matcher/list_param_matcher.dart new file mode 100644 index 000000000000..649ef67cceca --- /dev/null +++ b/samples/openapi3/client/petstore/dart-dio-next/petstore_client_lib_fake_tests/test/matcher/list_param_matcher.dart @@ -0,0 +1,20 @@ +import 'package:dio/src/parameter.dart'; +import 'package:meta/meta.dart'; +import 'package:collection/collection.dart'; +import 'package:http_mock_adapter/src/matchers/matcher.dart'; + +class ListParamMatcher extends Matcher { + final ListParam expected; + + const ListParamMatcher({@required this.expected}); + + @override + bool matches(dynamic actual) { + return actual is ListParam && + ListEquality().equals( + actual.value, + expected.value, + ) && + actual.format == expected.format; + } +}