question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG][DART-DIO] Dart dio generated code for map

See original GitHub issue
Description

When the body of the request is a map, a BuiltMap<String, JsonObject> is generated. Problem is that BuildMap doesn’t serialize itself as a map once used, so it’s not coherent with what’s in the definition.

BuiltMap generate this json:

{"$":"encoded_map","{\"$\":\"String\",\"\":\"key\"}":{"$":"JsonObject","":"input2"},"{\"$\":\"String\",\"\":\"value\"}":{"$":"JsonObject","":""}}

Where we want:

{"key": "value"}
openapi-generator version

5.0.0

OpenAPI declaration file content or url
/api/v1/plugins/{pluginName}/{deviceId}:
    parameters:
      - name: deviceId
        in: path
        required: true
        schema:
          type: integer
      - name: pluginName
        in: path
        required: true
        schema:
          type: string
    post:
      operationId: updateDevice
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties:
                 type: object

Results:

Generated today:

/// 
    ///
    /// 
    Future<Response<Device>> updateDevice(
        int deviceId,
        String pluginName,      
        BuiltMap<String, JsonObject> requestBody, { 
        CancelToken cancelToken,
        Map<String, dynamic> headers,
        Map<String, dynamic> extra,
        ValidateStatus validateStatus,
        ProgressCallback onSendProgress,
        ProgressCallback onReceiveProgress,
    }) async {
           final String _path = '/api/v1/plugins/{pluginName}/{deviceId}'.replaceAll('{' r'deviceId' '}', deviceId.toString()).replaceAll('{' r'pluginName' '}', pluginName.toString());

        final Map<String, dynamic> queryParams = {};
        final Map<String, dynamic> headerParams = {
            if (headers != null) ...headers,
        };
        dynamic bodyData;

        queryParams.removeWhere((key, value) => value == null);
        headerParams.removeWhere((key, value) => value == null);

        final List<String> contentTypes = [
            'application/json',
        ];

        final serializedBody = _serializers.serialize(requestBody);
        final jsonrequestBody = json.encode(serializedBody);
        bodyData = jsonrequestBody;

        return _dio.request(
            _path,
            queryParameters: queryParams,
            data: bodyData,
            options: Options(
                method: 'post'.toUpperCase(),
                headers: headerParams,
                extra: {
                    'secure': [
                        {
                            'type': 'apiKey',
                            'name': 'Bearer',
                            'keyName': 'Authorization',
                            'where': 'header',
                        },
                    ],
                    if (extra != null) ...extra,
                },
                validateStatus: validateStatus,
                contentType: contentTypes.isNotEmpty ? contentTypes[0] : 'application/json',
            ),
            cancelToken: cancelToken,
            onSendProgress: onSendProgress,
            onReceiveProgress: onReceiveProgress,
        ).then((response) {
            final serializer = _serializers.serializerForType(Device);
            final data = _serializers.deserializeWith<Device>(serializer, response.data is String ? jsonDecode(response.data) : response.data);

            return Response<Device>(
                data: data,
                headers: response.headers,
                request: response.request,
                redirects: response.redirects,
                statusCode: response.statusCode,
                statusMessage: response.statusMessage,
                extra: response.extra,
            );
        });
    }

Wanted:

///
    ///
    ///
    Future<Response<Device>> updateDevice(
        int deviceId,
        String pluginName,
        Map<String, Object> requestBody, {
        CancelToken cancelToken,
        Map<String, dynamic> headers,
        Map<String, dynamic> extra,
        ValidateStatus validateStatus,
        ProgressCallback onSendProgress,
        ProgressCallback onReceiveProgress,
    }) async {
        final String _path = '/api/v1/plugins/{pluginName}/{deviceId}'.replaceAll('{' r'deviceId' '}', deviceId.toString()).replaceAll('{' r'pluginName' '}', pluginName.toString());

        final Map<String, dynamic> queryParams = {};
        final Map<String, dynamic> headerParams = {
            if (headers != null) ...headers,
        };
        dynamic bodyData;

        queryParams.removeWhere((key, value) => value == null);
        headerParams.removeWhere((key, value) => value == null);

        final List<String> contentTypes = [
            'application/json',
        ];

        final serializedBody = (requestBody);
        final jsonrequestBody = json.encode(serializedBody);
        bodyData = jsonrequestBody;

        return _dio.request(
            _path,
            queryParameters: queryParams,
            data: bodyData,
            options: Options(
                method: 'post'.toUpperCase(),
                headers: headerParams,
                extra: {
                    'secure': [
                        {
                            'type': 'apiKey',
                            'name': 'Bearer',
                            'keyName': 'Authorization',
                            'where': 'header',
                        },
                    ],
                    if (extra != null) ...extra,
                },
                validateStatus: validateStatus,
                contentType: contentTypes.isNotEmpty ? contentTypes[0] : 'application/json',
            ),
            cancelToken: cancelToken,
            onSendProgress: onSendProgress,
            onReceiveProgress: onReceiveProgress,
        ).then((response) {
            final serializer = _serializers.serializerForType(Device);
            final data = _serializers.deserializeWith<Device>(serializer, response.data is String ? jsonDecode(response.data) : response.data);

            return Response<Device>(
                data: data,
                headers: response.headers,
                request: response.request,
                redirects: response.redirects,
                statusCode: response.statusCode,
                statusMessage: response.statusMessage,
                extra: response.extra,
            );
        });
    }
Suggest a fix

Not sure why but under a model class it generate Map<String, Object> so why not generate that too when the body is a map.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:11 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
jaumardcommented, Jan 21, 2021

I was using the jaguar generator 😃 but as jaguar is not maintained anymore I wanted to switch to dio because I like it. My API is mostly typed but I have one or two endpoint with full dynamic data in this project, we use this generator at work too and no issues as we’re fully typed ^^

I’ll try to use custom extension, I forget about those might make things a bit easier and hide the shit in one place lol 😄

Thanks for your help!!!

1reaction
kuhnroyalcommented, Jan 21, 2021

FYI you can use ```yaml and ```dart to enable syntax highlighting for the code blocks, makes it a bit easier to read. If you have any more problems with dart-dio, feel free to mention me in the ticket.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Documentation for the dart-dio Generator
Generates a Dart Dio client library with null-safety. #CONFIG OPTIONS. These options may be applied as additional-properties (cli) or ...
Read more >
flutter - OpenAPI generated client combine with GetX form
yaml -g dart-dio -o ./api_generated . The generator is using built_value and I'm trying to make it work with GetX features like observables...
Read more >
Generating Dart REST API client libraries using OpenAPI ...
Creating an OpenAPI (or Swagger) spec file is outside the scope of this post, but we're going to take a look at how...
Read more >
Generate REST API clients using OpenAPI in Flutter — Daniel ...
Tired of manually writing client code to connect your application to your REST API endpoints? We all are. But there is a solution:...
Read more >
Generator enum - openapi_generator_annotations library
dio → const Generator. This generator uses the dio package. Source gen is required after generating code with this generator corresponds to dart-dio....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found