Skip to content

[Dart] Add UInt8List support, allowing for type:string format:binary definitions #13451

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

0xNF
Copy link
Contributor

@0xNF 0xNF commented Sep 17, 2022

Summary

tl;dr UInt8List support, which Dart-Dio has, has been added to the regular Dart2 generator.

Fixes #12161.

Details

Changes to the Generators:

To support UInt8List in the generator, Typed Data imports had to be added. Additionally, some OpenAPI data types have been switched to Uint8List.

  • [AbstractDartCodeGen.java]: added Uint8List/dart:typed_data to the imports.
  • [AbstractDartCodeGen.java]: Changed typeMapping of {file, binary} to Uint8List away from MultiPartFile
  • [AbstractDartCodeGen.java]: Copied Multipart/Uint8list differentiation in postProcessOperationsWithModels from DartDioClientCodegen.java
  • [dart2/apilib.mustache]: Added import 'dart:typed_data';

Changes to the API classes

To support Uint8List in the generated API output, parts of the *api.dart files had to be refactored. Presently Dart2 relies on passing utf8 decoded response byte strings through its API calls, but this leads to errors because not all response objects are json strings. To handle this, I refactored many of the calls to take Uint8List's straight from response.bodyBytes. Decoding into a String object doesn't happen until it needs to, which is right before passing the object down into the Json Decoding section.

  • [api_client.dart]: deserialize and deserializeAsync now take Uint8List as their default input
  • [api_helper.dart]: removed _decodeBodyBytes in favor of just using response.bodyBytes
  • [api_helper.dart]: added decodeError method to deal with the byte response, which decodes the resposne into a utf-8 String.

To confirm this change, use the following specfile:

specfile
openapi: 3.0.3
info:
  version: "1.1"
  title: Dart Uint8list Demo
servers:
  - url: "localhost"
    variables:
      host:
        default: localhost
paths:
  /getData:
    get:
      operationId: GetData
      description: "Should return a Uint8List of bytes"
      responses:
        "200":
          description: Binary data
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
    put:
      operationId: PutData
      description: "Should push a Multipart File"
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                fileContent:
                  type: string
                  format: binary
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: string
  /item:
    get:
      operationId: GetItem
      description: "Should return an Item"
      responses:
        "200":
          description: items
          content:
            application/json:
              schema:
                $ref: "#components/schemas/item"
components:
  schemas:
    Item:
      type: object
      description: "Some json thing"
      required:
        - intField
        - doubleField
        - stringField
        - dateField
        - timeField
        - dateTimeField
        - boolField
        - b64Field
        - intArrayField
      properties:
        intField:
          type: integer
          format: int32
        doubleField:
          type: number
          format: float
        stringField:
          type: string
        dateField:
          type: string
          format: date
        timeField:
          type: string
          format: time
        dateTimeField:
          type: string
          format: date-time
        boolField:
          type: boolean
        b64Field:
          type: string
          format: byte
        intArrayField:
          type: array
          items:
            type: integer
            format: int32

PR checklist

  • Read the contribution guidelines.
  • Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work. Missing information here may result in delayed response from the community.
  • Run the following to build the project and update samples:
  • File the PR against the correct branch: master (6.1.0) (minor release - breaking changes with fallbacks), 7.0.x (breaking changes without fallbacks)
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

@jaumard @josh-burton @amondnet @sbu-WBT @kuhnroyal @agilob @ahmednfwela

@0xNF 0xNF changed the title Dart: Add UInt8List support, allowing for type:string format:binary definitions [Dart] Add UInt8List support, allowing for type:string format:binary definitions Sep 17, 2022
Copy link
Contributor

@ahmednfwela ahmednfwela left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are alot of whitespace changes here that are polluting the PR, it would be great if the PR had the bare minimum changes

class PetApi {
PetApi([ApiClient? apiClient]) : apiClient = apiClient ?? defaultApiClient;

final ApiClient apiClient;

/// Add a new pet to the store
///
///
///
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please avoid whitespace changes since they pollute the PR

///
/// Note: This method returns the HTTP [Response].
///
/// Parameters:
///
/// * [Pet] pet (required):
/// Pet object that needs to be added to the store
Future<Response> addPetWithHttpInfo(Pet pet,) async {
Future<Response> addPetWithHttpInfo(
Pet pet,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whitespace changes here too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The newest version of this branch should have corrected the extraneous whitespace.

@0xNF
Copy link
Contributor Author

0xNF commented Sep 17, 2022

When I get home I'll try to fix it, but I didn't touch any of those files by hand. I only ran the generate samples script. I didn't even open these in my editor.

@0xNF 0xNF force-pushed the fix_dart_uint8list branch from 5e715aa to 819c9f1 Compare September 18, 2022 04:40
@0xNF 0xNF requested a review from ahmednfwela September 18, 2022 04:44
return responseBytes;
}

final decodedString = const Utf8Decoder().convert(responseBytes);
// If the expected target type is String, nothing to do...
return targetType == 'String'
? json
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this return decodedString?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eagle-eye'd catch there. json isn't even a variable in the new method anymore, my mistake New push of the branch has it returning decodedString now.

* Adds Uint8List as a valid return type for type: string format: binary definitions
* Adds support for using bodyBytes instead of body for deserializing response data
@0xNF 0xNF force-pushed the fix_dart_uint8list branch from 819c9f1 to d5ed19f Compare September 19, 2022 02:19
@ahmednfwela
Copy link
Contributor

@kuhnroyal @wing328 Can you check why the tests were passing here when there was a compile error for the generated code?

@ahmednfwela
Copy link
Contributor

@0xNF did you make any changes in the java files? I can't see them in the PR

@0xNF
Copy link
Contributor Author

0xNF commented Sep 19, 2022

The Java changes seem to have gotten lost. Sorry this PR is kinda messy. I'm flipping between too many branches rn.

@wing328
Copy link
Member

wing328 commented Sep 19, 2022

@kuhnroyal @wing328 Can you check why the tests were passing here when there was a compile error for the generated code?

The test did run and passed. Does it has anything to do with Dart version?

      - uses: dart-lang/setup-dart@v1
        with:
          sdk: 2.14.0

That's what we use in the CI.

@ahmednfwela
Copy link
Contributor

dart 2 uses 2.12 in the generated code, which 2.14 should be able to run

@wing328
Copy link
Member

wing328 commented Sep 19, 2022

Can you please paste the compilation error here as well? I'll try to repeat that locally.

@0xNF
Copy link
Contributor Author

0xNF commented Sep 19, 2022

It's probably because I force pushed the update to my own branch, and the tests didn't re-run here.

@wing328
Copy link
Member

wing328 commented Sep 19, 2022

It's probably because I force pushed the update to my own branch, and the tests didn't re-run here.

To trigger the run, please update the samples and the Github action (dart job) will run again.

@0xNF
Copy link
Contributor Author

0xNF commented Sep 20, 2022

Should I be regenerating all samples? Up til now I've just been regenerating the relevant samples for my changes (Dart). But then the CI complains.

@wing328
Copy link
Member

wing328 commented Sep 20, 2022

@wing328 wing328 modified the milestones: 6.1.1, 6.2.1 Sep 24, 2022
@wing328 wing328 modified the milestones: 6.2.1, 6.3.0 Nov 1, 2022
@zmoshansky
Copy link

@0xNF @wing328 Is there any movement on this? It looks like this PR is functionally ready to land. Just needing some clean-up.

Currently, I'm facing an issue around this as passing a UInt8List to a generated API endpoint causes the following error:

DioError [DioErrorType.other]: Bad state: No serializer for 'Uint8List'.

Relevant Code (Generated API's model.dart):

    yield serializers.serialize(
      object.appBinaryData,
      specifiedType: const FullType(Uint8List),
    );

@ahmednfwela
Copy link
Contributor

@zmoshansky this PR is for dart generator, and it seems like you are using the dart-dio generator, please create a new Issue with reproducible sample

@wing328 wing328 modified the milestones: 6.3.0, 6.3.1 Jan 20, 2023
@wing328 wing328 modified the milestones: 6.4.0, 6.5.0 Feb 19, 2023
@wing328 wing328 modified the milestones: 6.5.0, 6.6.0 Apr 1, 2023
@wing328 wing328 modified the milestones: 6.6.0, 7.0.0 May 11, 2023
@wing328 wing328 modified the milestones: 7.0.0, 7.0.1 Aug 25, 2023
@wing328 wing328 modified the milestones: 7.0.1, 7.1.0 Sep 20, 2023
@wing328 wing328 modified the milestones: 7.1.0, 7.2.0 Nov 13, 2023
@wing328 wing328 modified the milestones: 7.2.0, 7.3.0 Dec 22, 2023
@wing328 wing328 modified the milestones: 7.3.0, 7.4.0 Feb 8, 2024
@wing328 wing328 modified the milestones: 7.4.0, 7.5.0 Mar 11, 2024
@wing328 wing328 modified the milestones: 7.5.0, 7.6.0 Apr 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] [Dart] Response type of application/octet-stream with format: binary are unusable
4 participants