Carapacik / swagger_parser

Dart package that takes an OpenApi definition file and generates REST clients based on retrofit and data classes for your project.
https://pub.dev/packages/swagger_parser
MIT License
96 stars 43 forks source link

Issue with $ref Schema Handling: Incorrect Required Property and Missing Description in Generated Dart Code #257

Open naipaka opened 3 weeks ago

naipaka commented 3 weeks ago

Steps to reproduce

  1. Define swagger_parser: 1.18.1 or 1.18.2 in pubspec.yaml.
  2. Define the yaml file as described in Your OpenApi snippet.
  3. Run dart run swagger_parser.
  4. Run flutter pub run build_runner build -d.

Expected results

I would like the code to be generated as follows.

import 'package:freezed_annotation/freezed_annotation.dart';

import 'gender.dart';

part 'user_request.freezed.dart';
part 'user_request.g.dart';

/// User request.
@Freezed()
class UserRequest with _$UserRequest {
  const factory UserRequest({
    /// User name.
    required String name,

    /// User gender.
   Gender? gender,
  }) = _UserRequest;

  factory UserRequest.fromJson(Map<String, Object?> json) => _$UserRequestFromJson(json);
}

Actual results

Specifically:

  1. When a property is referenced using $ref, it becomes required even if it is not listed in the required section of the schema.
  2. If nullable: true is specified in the referenced schema (e.g., Gender), it should be reflected in the generated Dart code. However, the required annotation is still added, making the property non-nullable.
  3. Additionally, when using $ref, the description specified in the referenced schema is not carried over into the generated doc comments.

Generated Dart Code:

import 'package:freezed_annotation/freezed_annotation.dart';

import 'gender.dart';

part 'user_request.freezed.dart';
part 'user_request.g.dart';

/// User request.
@Freezed()
class UserRequest with _$UserRequest {
  const factory UserRequest({
    /// User name.
    required String name,
    required Gender gender,
  }) = _UserRequest;

  factory UserRequest.fromJson(Map<String, Object?> json) => _$UserRequestFromJson(json);
}

It would be helpful if the code generation could respect the nullable property and ensure that the description from the $ref schema is included in the generated code.

Your OpenApi snippet

openapi: 3.0.3

Example YAML:

paths:
  /sample:
    post:
      tags:
        - User
      summary: Sample API
      description: Sample API.
      operationId: PostSample
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserRequest'
      responses:
        '201':
          description: Created.
        default:
          $ref: '#/components/responses/default'
components:
  schemas:
    UserRequest:
      description: User request.
      type: object
      properties:
        name:
          type: string
          description: User name.
        gender:
          $ref: '#/components/schemas/Gender'
      required:
        # gender is not required, but required is added when generating code.
        - name
    Gender:
      type: string
      # here, even if you specify nullable, required is added when generating code.
      nullable: true
      enum:
        - MALE
        - FEMALE
        - OTHER
        - UNKNOWN
      # $ref is ignored description in code generation.
      description: User gender.

Code sample

The code sample is all as described above.

Logs

Logs ```console ┃ ____ _ _ _ ____ ____ ____ ____ ____ ___ ____ ____ ____ ____ ____ ┃ [__ | | | |__| | __ | __ |___ |__/ |__] |__| |__/ [__ |___ |__/ ┃ ___] |_|_| | | |__] |__] |___ | \ ___ | | | | \ ___] |___ | \ ┃ Generate... > api_client v1.0.0: 7 rest clients, 38 requests, 43 data classes. 52 files with 2 068 lines of code. Success (0.03 seconds) The generation was completed successfully. You can run the generation using build_runner. cd medeta_app_packages/api_client && flutter pub run build_runner build -d Deprecated. Use `dart run` instead. Building package executable... Built build_runner:build_runner. [INFO] Generating build script completed, took 150ms [INFO] Reading cached asset graph completed, took 59ms [INFO] Checking for updates since last build completed, took 416ms [INFO] Running build completed, took 1.4s [INFO] Caching finalized dependency graph completed, took 32ms [INFO] Succeeded after 1.5s with 3 outputs (6 actions) ```

Dart version and used packages versions

Dart version ```console ❯ flutter --version Flutter 3.24.1 • channel stable • https://github.com/flutter/flutter.git Framework • revision 5874a72aa4 (7 days ago) • 2024-08-20 16:46:00 -0500 Engine • revision c9b9d5780d Tools • Dart 3.5.1 • DevTools 2.37.2 ❯ dart --version Dart SDK version: 3.5.1 (stable) (Tue Aug 13 21:02:17 2024 +0000) on "macos_arm64" ```
Packages version ```console 1.18.1 or 1.18.2 ```
mhammerc commented 8 hours ago

Hello, thank you for this wonderful library!

I have the exact same problem.

mhammerc commented 8 hours ago

Version 1.16.3 does not have this bug. Version 1.16.4 and forward does have this bug!!

For what it's worth, here is the offending commit. https://github.com/Carapacik/swagger_parser/commit/bb6e08604eb65e6e41631c802b0f117f47909f3b

Let me know if I can be of any help!