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

Cannot generate code from specific swagger 2.0 spec. Not sure why it's failing #189

Closed
point-source opened this issue Jul 20, 2021 · 13 comments · Fixed by #194
Closed

Cannot generate code from specific swagger 2.0 spec. Not sure why it's failing #189

point-source opened this issue Jul 20, 2021 · 13 comments · Fixed by #194

Comments

@point-source
Copy link

I am having an issue parsing this spec: https://webapidemo.rentalworks.net/swagger/accountservices-v1/swagger.json

In fact, pretty much every spec from this site has issues with this generator. I am assuming there is something wrong with the spec itself but I'm having a hard time figuring out what since I'm not familiar with how these code generators currently work. It looks like it is incorrectly parsing. Any help would be appreciated. Thanks!

Build runner output:

[INFO] Generating build script completed, took 246ms
[INFO] Reading cached asset graph completed, took 30ms
[INFO] Checking for updates since last build completed, took 247ms
[WARNING] swagger_dart_code_generator:swagger_dart_code_generator on lib/swagger/account_services.swagger:
[WARNING] Code formatting failed.
          Please raise an issue on https://github.com/epam-cross-platform-lab/swagger-dart-code-generator/issues/
          Reason: Could not format because the source could not be parsed:

line 1867, column 28 of .: Expected a class member.
     ╷
1867 │     factory Func<Task<string>>.fromJson(Map<String, dynamic> json) => _$Func<Task<string>>FromJson(json);
     │                               ^
     ╵
line 1449, column 20 of .: A function body must be provided.
     ╷
1449 │     final Func%3CTask%3Cstring%3E%3E? jtiGenerator;
     │                       ^
     ╵
line 1449, column 32 of .: Expected a class member.
     ╷
1449 │     final Func%3CTask%3Cstring%3E%3E? jtiGenerator;
     │                                   ^^
     ╵
line 1449, column 13 of .: A function body must be provided.
     ╷
1449 │     final Func%3CTask%3Cstring%3E%3E? jtiGenerator;
     │                ^
     ╵
line 1449, column 29 of .: Expected a class member.
     ╷
1449 │     final Func%3CTask%3Cstring%3E%3E? jtiGenerator;
     │                                ^^
     ╵
line 1867, column 14 of .: Constructors can't have type parameters.
     ╷
1867 │     factory Func<Task<string>>.fromJson(Map<String, dynamic> json) => _$Func<Task<string>>FromJson(json);
     │                 ^^^^^^^^^^^^^^
     ╵
line 1449, column 20 of .: Expected a class member.
     ╷
1449 │     final Func%3CTask%3Cstring%3E%3E? jtiGenerator;
     │                       ^
     ╵
line 1449, column 36 of .: A function body must be provided.
     ╷
1449 │     final Func%3CTask%3Cstring%3E%3E? jtiGenerator;
     │                                       ^^^^^^^^^^^^
     ╵
line 1867, column 28 of .: A function body must be provided.
     ╷
1867 │     factory Func<Task<string>>.fromJson(Map<String, dynamic> json) => _$Func<Task<string>>FromJson(json);
     │                               ^
     ╵
line 1449, column 32 of .: A function body must be provided.
     ╷
1449 │     final Func%3CTask%3Cstring%3E%3E? jtiGenerator;
     │                                   ^^
     ╵
(44 more errors...)
[SEVERE] chopper_generator:chopper_generator on lib/generated_code/account_services.swagger.dart:

This builder requires Dart inputs without syntax errors.
However, package:rentalworks/generated_code/account_services.swagger.dart (or an existing part) contains the following errors.
account_services.swagger.dart:1889:40: Unexpected text 'on'.
account_services.swagger.dart:1449:31: Operator declarations must be preceded by the keyword 'operator'.
account_services.swagger.dart:1449:14: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
And 51 more...

Try fixing the errors and re-running the build.

[SEVERE] json_serializable:json_serializable on lib/generated_code/account_services.swagger.dart:

This builder requires Dart inputs without syntax errors.
However, package:rentalworks/generated_code/account_services.swagger.dart (or an existing part) contains the following errors.
account_services.swagger.dart:1889:40: Unexpected text 'on'.
account_services.swagger.dart:1449:31: Operator declarations must be preceded by the keyword 'operator'.
account_services.swagger.dart:1449:14: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
And 51 more...

Try fixing the errors and re-running the build.

[INFO] Running build completed, took 543ms
[INFO] Caching finalized dependency graph completed, took 20ms
[SEVERE] Failed after 569ms
@point-source point-source changed the title Cannot generate code from swagger 2.0 spec. Not sure why it's failing Cannot generate code from specific swagger 2.0 spec. Not sure why it's failing Jul 20, 2021
@Vovanella95
Copy link
Collaborator

Hi @point-source ,

I will check this issue ASAP

@Vovanella95
Copy link
Collaborator

@point-source I can't open this link
https://webapidemo.rentalworks.net/swagger/accountservices-v1/swagger.json

Can you please share this swagger file?

@point-source
Copy link
Author

Strange, I seem to be able to access it without any credentials/auth. What kind of error do you get?

I have also added it as a gist here: https://gist.github.com/point-source/5ac94a577ff56c6d48de0682b3739d53

@Vovanella95
Copy link
Collaborator

@point-source thanks, I'll check it tomorrow!

@Vovanella95
Copy link
Collaborator

THis one fails because your models has "+" symbols in names :D

Working on fix

@point-source
Copy link
Author

I actually noticed this and did a quick find/replace and replaced them with '-'. I also filed a bug report with the provider of this spec since it is non-compliant with the openapi official spec.

This fix allowed the models to build (with the build only models option) but the chopper classes still fail if I disable that option.

@Vovanella95
Copy link
Collaborator

@point-source I'll let you know when this file will generated without errors. Just wait a little. Already working ot in

@point-source
Copy link
Author

Sure thing. Thank you so much for the excellent support here!

@Vovanella95
Copy link
Collaborator

Ok now your file generated well!

I will check my changes on all my beatifull collection of swaggers and if everything is OK - release 2.0.9

Now you can use git ref in pubspec.yaml

swagger_dart_code_generator:
git:
url: https://github.com/epam-cross-platform-lab/swagger-dart-code-generator.git
ref: version/2.0.9

@point-source
Copy link
Author

point-source commented Jul 22, 2021

Testing now. Generation looks good, no errors. Trying to actually test against the api right now and getting a decode error. Trying to figure out if that's on my side or not.

Just for info, the error is: _TypeError (type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'FwCoreControllersFwJwtControllerJwtResponseModel?')

Occuring on the return line (copyWith) of decodeJson method of the chopper JsonConverter class.

I have confirmed the actual returned json from the server has matching keys with the model it is trying to convert to.

@point-source
Copy link
Author

point-source commented Jul 22, 2021

Ah yep, looks like the replacement of the JsonSerializableConverter() with chopper.JsonConverter() is the culprit. Specifically the removal of this code from generation:

typedef JsonFactory<T> = T Function(Map<String, dynamic> json);

class CustomJsonDecoder {
  CustomJsonDecoder(this.factories);

  final Map<Type, JsonFactory> factories;

  dynamic decode<T>(dynamic entity) {
    if (entity is Iterable) {
      return _decodeList<T>(entity);
    }

    if (entity is T) {
      return entity;
    }

    if (entity is Map<String, dynamic>) {
      return _decodeMap<T>(entity);
    }

    return entity;
  }

  T _decodeMap<T>(Map<String, dynamic> values) {
    final jsonFactory = factories[T];
    if (jsonFactory == null || jsonFactory is! JsonFactory<T>) {
      return throw "Could not find factory for type $T. Is '$T: $T.fromJsonFactory' included in the CustomJsonDecoder instance creation in bootstrapper.dart?";
    }

    return jsonFactory(values);
  }

  List<T> _decodeList<T>(Iterable values) =>
      values.where((v) => v != null).map<T>((v) => decode<T>(v) as T).toList();
}

class JsonSerializableConverter extends chopper.JsonConverter {
  @override
  chopper.Response<ResultType> convertResponse<ResultType, Item>(
      chopper.Response response) {
    if (response.bodyString.isEmpty) {
      // In rare cases, when let's say 204 (no content) is returned -
      // we cannot decode the missing json with the result type specified
      return chopper.Response(response.base, null, error: response.error);
    }

    final jsonRes = super.convertResponse(response);
    return jsonRes.copyWith<ResultType>(
        body: jsonDecoder.decode<Item>(jsonRes.body) as ResultType);
  }
}

final jsonDecoder = CustomJsonDecoder(LassoJsonDecoderMappings);

Not saying we need to bring that code back but it does seem that they are not equivalent substitutes at the moment. After using the old custom converter, the generated code appears to work.

@point-source
Copy link
Author

Additionally, out of the 9 swagger files I have from this application, your fix has worked on 3 of them. Here are all of them so you can add them to your testing collection: https://www.dropbox.com/sh/2t3s99zsmgf89ar/AACGJzjw3cPRCCEMDMvn6is9a?dl=0

The ones that are working are:

  • account_services
  • exports
  • plugins

Let me know how I can help here. Thanks again

@Vovanella95
Copy link
Collaborator

Cool, I'll check it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants