Open
Description
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator (example)?
- Have you tested with the latest master to confirm the issue still exists?
- Have you searched for related issues/PRs?
- What's the actual output vs expected output?
- [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
When generating a Get request with content-type application/octet-stream
or text/event-stream
the output returns a MultipartFile
instead of the expected Stream<Uint8List>
.
The generated code then calls the deserialize
which fails with the exception Cannot deserialize
.
I expect the generated method to return Stream<Uint8List>
.
openapi-generator version
openapi-generator-cli 7.12.0-SNAPSHOT
OpenAPI declaration file content or url
ymal schema:
/api/open-ai/session/{id}:
get:
operationId: open_ai_session_retrieve
parameters:
- in: path
name: id
schema:
type: string
format: uuid
required: true
- in: path
name: message_id
schema:
type: string
format: uuid
required: true
tags:
- open-ai
security:
- cookieAuth: []
responses:
'200':
content:
application/octet-stream:
schema:
type: string
format: binary
description: ''
Output:
/// openAiChatSessionMessageRetrieve
///
///
/// Parameters:
/// * [id]
/// * [messageId]
/// * [cancelToken] - A [CancelToken] that can be used to cancel the operation
/// * [headers] - Can be used to add additional headers to the request
/// * [extras] - Can be used to add flags to the request
/// * [validateStatus] - A [ValidateStatus] callback that can be used to determine request success based on the HTTP status of the response
/// * [onSendProgress] - A [ProgressCallback] that can be used to get the send progress
/// * [onReceiveProgress] - A [ProgressCallback] that can be used to get the receive progress
///
/// Returns a [Future] containing a [Response] with a [MultipartFile] as data
/// Throws [DioException] if API call or serialization fails
Future<Response<MultipartFile>> openAiChatSessionMessageRetrieve({
required String id,
CancelToken? cancelToken,
Map<String, dynamic>? headers,
Map<String, dynamic>? extra,
ValidateStatus? validateStatus,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
}) async {
final _path = r'/api/open-ai/session/{id}/'
.replaceAll('{' r'id' '}', id.toString())
final _options = Options(
method: r'GET',
responseType: ResponseType.bytes,
headers: <String, dynamic>{
...?headers,
},
extra: <String, dynamic>{
...?extra,
},
validateStatus: validateStatus,
);
final _response = await _dio.request<Object>(
_path,
options: _options,
cancelToken: cancelToken,
onSendProgress: onSendProgress,
onReceiveProgress: onReceiveProgress,
);
MultipartFile? _responseData;
try {
final rawData = _response.data;
_responseData = rawData == null
? null
: deserialize<MultipartFile, MultipartFile>(rawData, 'MultipartFile',
growable: true); // CRASH ---> deserialize cannot create MultipartFile
} catch (error, stackTrace) {
throw DioException(
requestOptions: _response.requestOptions,
response: _response,
type: DioExceptionType.unknown,
error: error,
stackTrace: stackTrace,
);
}
return Response<MultipartFile>(
data: _responseData,
headers: _response.headers,
isRedirect: _response.isRedirect,
requestOptions: _response.requestOptions,
redirects: _response.redirects,
statusCode: _response.statusCode,
statusMessage: _response.statusMessage,
extra: _response.extra,
);
}
deserializer:
final _regList = RegExp(r'^List<(.*)>$');
final _regSet = RegExp(r'^Set<(.*)>$');
final _regMap = RegExp(r'^Map<String,(.*)>$');
ReturnType deserialize<ReturnType, BaseType>(dynamic value, String targetType,
{bool growable = true}) {
switch (targetType) {
case 'String':
return '$value' as ReturnType;
case 'int':
return (value is int ? value : int.parse('$value')) as ReturnType;
case 'bool':
if (value is bool) {
return value as ReturnType;
}
final valueString = '$value'.toLowerCase();
return (valueString == 'true' || valueString == '1') as ReturnType;
case 'double':
return (value is double ? value : double.parse('$value')) as ReturnType;
// Rest of models, but no MultipartFile
default:
RegExpMatch? match;
if (value is List && (match = _regList.firstMatch(targetType)) != null) {
targetType = match![1]!; // ignore: parameter_assignments
return value
.map<BaseType>((dynamic v) => deserialize<BaseType, BaseType>(
v, targetType,
growable: growable))
.toList(growable: growable) as ReturnType;
}
if (value is Set && (match = _regSet.firstMatch(targetType)) != null) {
targetType = match![1]!; // ignore: parameter_assignments
return value
.map<BaseType>((dynamic v) => deserialize<BaseType, BaseType>(
v, targetType,
growable: growable))
.toSet() as ReturnType;
}
if (value is Map && (match = _regMap.firstMatch(targetType)) != null) {
targetType = match![1]!.trim(); // ignore: parameter_assignments
return Map<String, BaseType>.fromIterables(
value.keys as Iterable<String>,
value.values.map((dynamic v) => deserialize<BaseType, BaseType>(
v, targetType,
growable: growable)),
) as ReturnType;
}
break;
}
throw Exception('Cannot deserialize');
}
Generation Details
open-generator-config.ymal
# Config options for the dart-dio generator
pubName: app_api
pubVersion: 0.0.1
pubDescription: "App API"
dateLibrary: core
serializationLibrary: json_serializable
equalityCheckMethod: equatable
Steps to reproduce
run
openapi-generator generate -i openapi_docs.yaml -g dart-dio -c open-generator-config.yaml --enable-post-process-file