openapi-generator
openapi-generator copied to clipboard
[BUG] [Dart] Default enums generate syntacticallly incorrect Dart files
Bug Report Checklist
- [x] Have you provided a full/minimal spec to reproduce the issue?
- [x] Have you validated the input using an OpenAPI validator (example)?
- [x] Have you tested with the latest master to confirm the issue still exists?
- [x] Have you searched for related issues/PRs?
- [x] What's the actual output vs expected output?
- [ ] [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
with_enums.dart
//
// AUTO-GENERATED FILE, DO NOT MODIFY!
//
// @dart=2.12
// ignore_for_file: unused_element, unused_import
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: constant_identifier_names
// ignore_for_file: lines_longer_than_80_chars
part of openapi.api;
class WithEnums {
/// Returns a new [WithEnums] instance.
WithEnums({
this.stringEnum = const WithEnumsStringEnumEnum._('strC'),
this.intEnum = const WithEnumsIntEnumEnum._(WithEnumsIntEnumEnum.number2),
});
WithEnumsStringEnumEnum stringEnum;
WithEnumsIntEnumEnum intEnum;
@override
bool operator ==(Object other) => identical(this, other) || other is WithEnums && other.stringEnum == stringEnum && other.intEnum == intEnum;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(stringEnum.hashCode) + (intEnum.hashCode);
@override
String toString() => 'WithEnums[stringEnum=$stringEnum, intEnum=$intEnum]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
json[r'stringEnum'] = this.stringEnum;
json[r'intEnum'] = this.intEnum;
return json;
}
/// Returns a new [WithEnums] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static WithEnums? fromJson(dynamic value) {
if (value is Map) {
final json = value.cast<String, dynamic>();
// Ensure that the map contains the required keys.
// Note 1: the values aren't checked for validity beyond being non-null.
// Note 2: this code is stripped in release mode!
assert(() {
requiredKeys.forEach((key) {
assert(json.containsKey(key), 'Required key "WithEnums[$key]" is missing from JSON.');
assert(json[key] != null, 'Required key "WithEnums[$key]" has a null value in JSON.');
});
return true;
}());
return WithEnums(
stringEnum: WithEnumsStringEnumEnum.fromJson(json[r'stringEnum']) ?? 'strC',
intEnum: WithEnumsIntEnumEnum.fromJson(json[r'intEnum']) ?? WithEnumsIntEnumEnum.number2,
);
}
return null;
}
static List<WithEnums>? listFromJson(
dynamic json, {
bool growable = false,
}) {
final result = <WithEnums>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = WithEnums.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
static Map<String, WithEnums> mapFromJson(dynamic json) {
final map = <String, WithEnums>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = WithEnums.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
// maps a json object with a list of WithEnums-objects as value to a dart map
static Map<String, List<WithEnums>> mapListFromJson(
dynamic json, {
bool growable = false,
}) {
final map = <String, List<WithEnums>>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = WithEnums.listFromJson(
entry.value,
growable: growable,
);
if (value != null) {
map[entry.key] = value;
}
}
}
return map;
}
/// The list of required keys that must be present in a JSON.
static const requiredKeys = <String>{};
}
class WithEnumsStringEnumEnum {
/// Instantiate a new enum with the provided [value].
const WithEnumsStringEnumEnum._(this.value);
/// The underlying value of this enum member.
final String value;
@override
String toString() => value;
String toJson() => value;
static const strA = WithEnumsStringEnumEnum._(r'strA');
static const strB = WithEnumsStringEnumEnum._(r'strB');
static const strC = WithEnumsStringEnumEnum._(r'strC');
/// List of all possible values in this [enum][WithEnumsStringEnumEnum].
static const values = <WithEnumsStringEnumEnum>[
strA,
strB,
strC,
];
static WithEnumsStringEnumEnum? fromJson(dynamic value) => WithEnumsStringEnumEnumTypeTransformer().decode(value);
static List<WithEnumsStringEnumEnum>? listFromJson(
dynamic json, {
bool growable = false,
}) {
final result = <WithEnumsStringEnumEnum>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = WithEnumsStringEnumEnum.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
}
/// Transformation class that can [encode] an instance of [WithEnumsStringEnumEnum] to String,
/// and [decode] dynamic data back to [WithEnumsStringEnumEnum].
class WithEnumsStringEnumEnumTypeTransformer {
factory WithEnumsStringEnumEnumTypeTransformer() => _instance ??= const WithEnumsStringEnumEnumTypeTransformer._();
const WithEnumsStringEnumEnumTypeTransformer._();
String encode(WithEnumsStringEnumEnum data) => data.value;
/// Decodes a [dynamic value][data] to a WithEnumsStringEnumEnum.
///
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
///
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
/// and users are still using an old app with the old code.
WithEnumsStringEnumEnum? decode(dynamic data, {bool allowNull = true}) {
if (data != null) {
switch (data.toString()) {
case r'strA':
return WithEnumsStringEnumEnum.strA;
case r'strB':
return WithEnumsStringEnumEnum.strB;
case r'strC':
return WithEnumsStringEnumEnum.strC;
default:
if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
}
}
}
return null;
}
/// Singleton [WithEnumsStringEnumEnumTypeTransformer] instance.
static WithEnumsStringEnumEnumTypeTransformer? _instance;
}
class WithEnumsIntEnumEnum {
/// Instantiate a new enum with the provided [value].
const WithEnumsIntEnumEnum._(this.value);
/// The underlying value of this enum member.
final int value;
@override
String toString() => value.toString();
int toJson() => value;
static const number0 = WithEnumsIntEnumEnum._(0);
static const number1 = WithEnumsIntEnumEnum._(1);
static const number2 = WithEnumsIntEnumEnum._(2);
/// List of all possible values in this [enum][WithEnumsIntEnumEnum].
static const values = <WithEnumsIntEnumEnum>[
number0,
number1,
number2,
];
static WithEnumsIntEnumEnum? fromJson(dynamic value) => WithEnumsIntEnumEnumTypeTransformer().decode(value);
static List<WithEnumsIntEnumEnum>? listFromJson(
dynamic json, {
bool growable = false,
}) {
final result = <WithEnumsIntEnumEnum>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = WithEnumsIntEnumEnum.fromJson(row);
if (value != null) {
result.add(value);
}
}
}
return result.toList(growable: growable);
}
}
/// Transformation class that can [encode] an instance of [WithEnumsIntEnumEnum] to int,
/// and [decode] dynamic data back to [WithEnumsIntEnumEnum].
class WithEnumsIntEnumEnumTypeTransformer {
factory WithEnumsIntEnumEnumTypeTransformer() => _instance ??= const WithEnumsIntEnumEnumTypeTransformer._();
const WithEnumsIntEnumEnumTypeTransformer._();
int encode(WithEnumsIntEnumEnum data) => data.value;
/// Decodes a [dynamic value][data] to a WithEnumsIntEnumEnum.
///
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
///
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
/// and users are still using an old app with the old code.
WithEnumsIntEnumEnum? decode(dynamic data, {bool allowNull = true}) {
if (data != null) {
switch (data.toString()) {
case 0:
return WithEnumsIntEnumEnum.number0;
case 1:
return WithEnumsIntEnumEnum.number1;
case 2:
return WithEnumsIntEnumEnum.number2;
default:
if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
}
}
}
return null;
}
/// Singleton [WithEnumsIntEnumEnumTypeTransformer] instance.
static WithEnumsIntEnumEnumTypeTransformer? _instance;
}
For integer enums, the constructor is invalid:
WithEnums({
this.intEnum = const WithEnumsIntEnumEnum._(WithEnumsIntEnumEnum.number2),
});
WithEnumsIntEnumEnum.number2 isn't a valid input to the enum constructor.
For string enums, the constructor is fine, but the fromJson method contains errors:
static WithEnums? fromJson(dynamic value) {
if (value is Map) {
final json = value.cast<String, dynamic>();
/* omitted */
return WithEnums(
stringEnum: WithEnumsStringEnumEnum.fromJson(json[r'stringEnum']) ?? 'strC',
);
}
return null;
}
This is incorrect because a raw string value isn't a valid enum value.
openapi-generator version
Latest commit as of 9/18/22 (863dbc7c3ee39af1ac931d2949388f7f84896ec4)
OpenAPI declaration file content or url
Specfile
openapi: 3.0.3
info:
version: "1.1"
title: Dart Uint8list Demo
servers:
- url: "localhost"
variables:
host:
default: localhost
paths:
/item:
get:
operationId: GetItem
description: "Should return an Item"
responses:
"200":
description: items
content:
application/json:
schema:
$ref: "#components/schemas/item"
components:
schemas:
WithEnums:
type: object
properties:
stringEnum:
type: string
enum:
- strA
- strB
- strC
default: strC
intEnum:
type: integer
enum:
- 0
- 1
- 2
default: 2
Generation Details
Suggest a fix
Mustache template tweaks are required.