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
87 stars 33 forks source link

`"anyOf"` keyword doesn't implement any relationship with a parent model #225

Open tsinis opened 2 months ago

tsinis commented 2 months ago

Steps to reproduce

Hey, again @Carapacik, thanks for a great package!

I have a question related to the "anyOf" declaration in the JSON schemas, looks like the parent class doesn't utilize/reference members of the "anyOf" list at all.

  1. Clone swagger_parser/example.
  2. Replace schemes/openapi.json content with the content of test anyOf schema.
  3. Provide json_serializer: freezed in the swagger_parser.yaml.
  4. dart pub get.
  5. dart run swagger_parser.

Fruit class is not anyhow related to the Apple/Banana at all, so the "anyOf" keyword has no practical effect.

Expected results

// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, unused_import

import 'package:freezed_annotation/freezed_annotation.dart';

import 'apple.dart';
import 'banana.dart';

part 'fruit.freezed.dart';
part 'fruit.g.dart';

@Freezed()
class Fruit with _$Fruit {
  const factory Fruit.apple(Apple apple, {required String color}) = _AppleFruit;
  const factory Fruit.banana(Banana banana, {required String color}) =
      _BananaFruit;

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

Actual results

// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint, unused_import

import 'package:freezed_annotation/freezed_annotation.dart';

part 'fruit.freezed.dart';
part 'fruit.g.dart';

@Freezed()
class Fruit with _$Fruit {
  const factory Fruit({
    required String color,
  }) = _Fruit;

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

Your OpenApi snippet

{
  "openapi": "3.0.1",
  "info": {
    "title": "fruity",
    "version": "0.0.1"
  },
  "paths": {
    "/": {
      "get": {
        "responses": {
          "200": {
            "description": "desc",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/fruit"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "fruit": {
        "title": "fruit",
        "type": "object",
        "properties": {
          "color": {
            "type": "string"
          }
        },
        "anyOf": [
          {
            "$ref": "#/components/schemas/apple"
          },
          {
            "$ref": "#/components/schemas/banana"
          }
        ]
      },
      "apple": {
        "title": "apple",
        "type": "object",
        "properties": {
          "kind": {
            "type": "string"
          }
        }
      },
      "banana": {
        "title": "banana",
        "type": "object",
        "properties": {
          "count": {
            "type": "number"
          }
        }
      }
    }
  }
}

Code sample

Since Fruit is a union/sealed class, that might be either banana or apple - it should be reflected in the Fruit's freezed class declaration. Otherwise "anyOf" doesn't have any effect on resulted code-gen.

Code sample ```dart /// This is sadly not working :( because Apple and Banana are not related to the Fruit. const fruit = Fruit.apple(Apple(kind: "gala"), color: "red"); print('this is ${fruit.color} and'); fruit.when( apple: (apple, _) => print("it's ${apple.kind} apple!"), banana: (banana, _) => print("it's ${banana.count} banana(s)!")); ```

Logs

Logs ```console Building package executable... Built swagger_parser:swagger_parser. ┃ ____ _ _ _ ____ ____ ____ ____ ____ ___ ____ ____ ____ ____ ____ ┃ [__ | | | |__| | __ | __ |___ |__/ |__] |__| |__/ [__ |___ |__/ ┃ ___] |_|_| | | |__] |__] |___ | \ ___ | | | | \ ___] |___ | \ ┃ Generate... > swagger v0.0.1: 1 rest clients, 1 requests, 3 data classes. 6 files with 105 lines of code. Success (0.014 seconds) The generation was completed successfully. You can run the generation using build_runner. ```

Dart version and used packages versions

Dart version ```console #### General info - Dart 3.3.4 (stable) (Tue Apr 16 19:56:12 2024 +0000) on "macos_arm64" - on macos / Version 14.4.1 (Build 23E224) - locale is en-US #### Project info - sdk constraint: '^3.3.0' - dependencies: dio, freezed_annotation, json_annotation, path, retrofit - dev_dependencies: analyzer, build_runner, freezed, json_serializable, retrofit_generator, swagger_parser - elided dependencies: 1 ```
Packages version ```console environment: sdk: ^3.3.0 dependencies: dio: ^5.4.3+1 freezed_annotation: ^2.4.1 json_annotation: ^4.8.1 path: ^1.9.0 retrofit: ^4.1.0 dev_dependencies: analyzer: ^6.4.1 build_runner: ^2.4.9 freezed: ^2.5.2 index_generator: ^3.4.1 json_serializable: ^6.7.1 retrofit_generator: ^8.1.0 swagger_parser: ^1.17.2 ```