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
94 stars 43 forks source link

Feature: Enum prefix #29

Closed JasCodes closed 1 year ago

JasCodes commented 1 year ago

Most time enum name are like 'type', 'status'. Which is not very good enum from global POV. I am currently using 'swagger_dart_code_generator'. The way they are handling is by prefixing enum with return type. And turns out practically very good solution. This can be a non-default flag if you disagree about it as default behaviour.

Sancene commented 1 year ago

Can you please provide an example of such a prefixed enum?

JasCodes commented 1 year ago

@Sancene Here is an example

factory BlockFeedbackResponse.fromJson(Map<String, dynamic> json) =>
      _$BlockFeedbackResponseFromJson(json);

  @JsonKey(name: 'student')
  final MiniStudentResponse student;
  @JsonKey(name: 'teacher')
  final MiniTeacherResponse teacher;
  @JsonKey(name: 'id')
  final double id;
  @JsonKey(name: 'createdAt')
  final DateTime createdAt;
  @JsonKey(
    name: 'attendance',
    toJson: blockFeedbackResponseAttendanceToJson,
    fromJson: blockFeedbackResponseAttendanceFromJson,
  )
  final enums.BlockFeedbackResponseAttendance attendance;
  @JsonKey(
    name: 'status',
    toJson: blockFeedbackResponseStatusToJson,
    fromJson: blockFeedbackResponseStatusFromJson,
  )
  final enums.BlockFeedbackResponseStatus status;
  @JsonKey(name: 'comment')
  final String? comment;
  static const fromJsonFactory = _$BlockFeedbackResponseFromJson;
  static const toJsonFactory = _$BlockFeedbackResponseToJson;
  Map<String, dynamic> toJson() => _$BlockFeedbackResponseToJson(this);

  @override
  bool operator ==(dynamic other) {
    return identical(this, other) ||
        (other is BlockFeedbackResponse &&
            (identical(other.student, student) ||
                const DeepCollectionEquality()
                    .equals(other.student, student)) &&
            (identical(other.teacher, teacher) ||
                const DeepCollectionEquality()
                    .equals(other.teacher, teacher)) &&
            (identical(other.id, id) ||
                const DeepCollectionEquality().equals(other.id, id)) &&
            (identical(other.createdAt, createdAt) ||
                const DeepCollectionEquality()
                    .equals(other.createdAt, createdAt)) &&
            (identical(other.attendance, attendance) ||
                const DeepCollectionEquality()
                    .equals(other.attendance, attendance)) &&
            (identical(other.status, status) ||
                const DeepCollectionEquality().equals(other.status, status)) &&
            (identical(other.comment, comment) ||
                const DeepCollectionEquality().equals(other.comment, comment)));
  }
JasCodes commented 1 year ago

@Carapacik I export all my repos, and in swagger like here there are enums which will confilct at global level. swagger_dart_code_generator from which I am trying to migrate from, solve it by prefixing all the enum with the return Type of the object. In the above example you can see status -> BlockFeedbackResponseStatus based on return type BlockFeedbackResponse. This is last hold out for me :)

Sancene commented 1 year ago

How will this work with enums that are listed in components, since they can be referenced in multiple places and dont have an ascendant object? I think this is possible only for enums contained within objects themselves.

JasCodes commented 1 year ago

How will this work with enums that are listed in components, since they can be referenced in multiple places and dont have an ascendant object? I think this is possible only for enums contained within objects themselves.

Yes, and another question for swagger_parser is; should this be by default?

Carapacik commented 1 year ago

Yes

JasCodes commented 1 year ago

@Carapacik Mate the other issue that we were discussing, I can just exclude upload module but this is more pressing for me.

In my open API there are many places where in Input DTO there is Enum Type that globaly conflicts. I understand you agreed with me but now this issue is marked as invalid. Please can you make further comment on this?

Sancene commented 1 year ago

So what you want from us is to add prefixes for enums parsed from json? So if we have a type enum it will be something like typeEnum?

JasCodes commented 1 year ago

When using swagger_dart_code_generator

"BlockStudentResponse": {
    "type": "object",
    "properties": {
        "student": {
            "$ref": "#/components/schemas/MiniStudentResponse"
        },
        "id": {
            "type": "number"
        },
        "type": {
            "type": "string",
            "enum": [
                "IN",
                "OUT"
            ]
        }
    },
    "required": [
        "student",
        "id",
        "type"
    ]
}

produces

enum BlockStudentResponseType {
  @JsonValue(null)
  swaggerGeneratedUnknown(null),

  @JsonValue('IN')
  $in('IN'),
  @JsonValue('OUT')
  out('OUT');

  final String? value;

  const BlockStudentResponseType(this.value);
}

But if you generate enum Type, it will conflict all over the place.

JasCodes commented 1 year ago

@Carapacik Can we please reopen this?

savage7 commented 1 year ago

I've the same problem. Basically in other languages inline enums are generated as nested enums in the dto class, which dart doesn't support. I also upvote a prefix, like the name of the parent dto, for inline enums. At least as an option, cannot think of another solution.

JasCodes commented 1 year ago

@savage7 I concur, last thing keeping me switching from swagger_dart_code_generator

Carapacik commented 1 year ago

@jascodes @savage7 Check latest(^1.3.0) version of package

savage7 commented 1 year ago

@Carapacik thank you you 🥇

JasCodes commented 1 year ago

@Carapacik mate one comment not too critical, Assuming status was property name when we generate enum on its type should be prefixed not the property name.

final ExamResponseStatus examResponseStatus;

should be

final ExamResponseStatus status;
Carapacik commented 1 year ago

Already working on this problem

Carapacik commented 1 year ago

Could you please send an example of the scheme, because I do not reproduce this (JsonKey(name: 'status') writes on top)?

@Carapacik mate one comment not too critical, Assuming status was property name when we generate enum on its type should be prefixed not the property name.

final ExamResponseStatus examResponseStatus;

should be

final ExamResponseStatus status;
JasCodes commented 1 year ago

Let take another example

"StudentAuthDto": {
                "type": "object",
                "properties": {
                    "firstName": {
                        "type": "string"
                    },
                    "lastName": {
                        "type": "string"
                    },
                    "gender": {
                        "type": "string",
                        "enum": [
                            "male",
                            "female",
                            "other"
                        ]
                    }
                },
                "required": [
                    "firstName",
                    "lastName",
                ]
            },
import 'package:json_annotation/json_annotation.dart';

import 'student_auth_dto_gender.dart';

part 'student_auth_dto.g.dart';

@JsonSerializable()
class StudentAuthDto {
  const StudentAuthDto({
    required this.firstName,
    required this.lastName,
    required this.studentAuthDtoGender,
  });

  factory StudentAuthDto.fromJson(Map<String, Object?> json) => _$StudentAuthDtoFromJson(json);

  final String firstName;
  final String lastName;
  @JsonKey(name: 'gender')
  final StudentAuthDtoGender studentAuthDtoGender;

  Map<String, Object?> toJson() => _$StudentAuthDtoToJson(this);
}

I am just saying

final StudentAuthDtoGender studentAuthDtoGender;

should be

final StudentAuthDtoGender gender;

while one the enum should be only prefixed.

Thanks

Carapacik commented 1 year ago

Do I understand correctly that to make the name of the variable also gender and leave the type StudentAuthDtoGender?

JasCodes commented 1 year ago

Correct, don't you think that's cleaner solution?

Carapacik commented 1 year ago

Any one suits me, but yours seems much more beautiful.

JasCodes commented 1 year ago

Upto you mate, Conflict will only occur with enum name. But I shared my opinion. :)