From 00c6c3aeb28031c2e1a50c8ad778c791a3a33f1d Mon Sep 17 00:00:00 2001 From: StarProxima Date: Mon, 23 Oct 2023 23:33:02 +0300 Subject: [PATCH 1/9] Unknown enum value --- .../templates/dart_enum_dto_template.dart | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart b/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart index 6207033a..384de24c 100644 --- a/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart +++ b/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart @@ -20,28 +20,31 @@ ${generatedFileComment( ${descriptionComment(enumClass.description)}@JsonEnum() enum $className { -${enumClass.items.mapIndexed((i, e) => _jsonValue(i, enumClass.type, e)).join(',\n')}; -${enumsToJson ? _toJson(enumClass, className) : '}'} +${enumClass.items.mapIndexed((i, e) => _enumValue(i, enumClass.type, e)).join(',\n')}, + + /// Default value for all unparsed values, allows backward compatibility when adding new values on the backend. + \$unknown(null); + + const $className(this.json); + + factory $className.fromJson(String json) => values.firstWhere( + (e) => e.json == json, + orElse: () => \$unknown, + ); + + final ${enumClass.type.toDartType()}? json;${enumsToJson ? _toJson(enumClass, className) : ''} +} '''; } -String _jsonValue( +String _enumValue( int index, String type, UniversalEnumItem item, ) => ''' -${index != 0 && item.description != null ? '\n' : ''}${descriptionComment(item.description, tab: ' ')} @JsonValue(${type == 'string' ? "'${item.jsonKey}'" : item.jsonKey}) - ${item.name.toCamel}'''; - -String _toJson(UniversalEnumClass enumClass, String className) => ''' - - ${enumClass.type.toDartType()} toJson() => _\$${className}EnumMap[this]!; -} +${index != 0 ? '\n' : ''}${descriptionComment(item.description, tab: ' ')} @JsonValue(${type == 'string' ? "'${item.jsonKey}'" : item.jsonKey}) + ${item.name.toCamel}('${item.jsonKey}')'''; -const _\$${className}EnumMap = { - ${enumClass.items.map( - (e) => '$className.${e.name.toCamel}: ' - '${enumClass.type == 'string' ? "'" : ''}${e.jsonKey}${enumClass.type == 'string' ? "'" : ''}', - ).join(',\n ')}, -};'''; +String _toJson(UniversalEnumClass enumClass, String className) => + '\n\n ${enumClass.type.toDartType()}? toJson() => json;'; From e5d291b66875c9b581720ba7c634280f72ebaa7c Mon Sep 17 00:00:00 2001 From: StarProxima Date: Tue, 24 Oct 2023 00:24:20 +0300 Subject: [PATCH 2/9] Fix quotation marks in enum json --- .../lib/src/generator/templates/dart_enum_dto_template.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart b/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart index 384de24c..e678fc5d 100644 --- a/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart +++ b/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart @@ -44,7 +44,7 @@ String _enumValue( ) => ''' ${index != 0 ? '\n' : ''}${descriptionComment(item.description, tab: ' ')} @JsonValue(${type == 'string' ? "'${item.jsonKey}'" : item.jsonKey}) - ${item.name.toCamel}('${item.jsonKey}')'''; + ${item.name.toCamel}(${type == 'string' ? "'${item.jsonKey}'" : item.jsonKey})'''; String _toJson(UniversalEnumClass enumClass, String className) => '\n\n ${enumClass.type.toDartType()}? toJson() => json;'; From 0918e6a5fa4a1dd4089130e9a1c1284efbda86e8 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Tue, 24 Oct 2023 14:32:23 +0300 Subject: [PATCH 3/9] Fix json type in enum fromJson --- .../lib/src/generator/templates/dart_enum_dto_template.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart b/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart index e678fc5d..c2c9639c 100644 --- a/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart +++ b/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart @@ -27,7 +27,7 @@ ${enumClass.items.mapIndexed((i, e) => _enumValue(i, enumClass.type, e)).join(', const $className(this.json); - factory $className.fromJson(String json) => values.firstWhere( + factory $className.fromJson(${enumClass.type.toDartType()} json) => values.firstWhere( (e) => e.json == json, orElse: () => \$unknown, ); From c104e8d9cbbcf20920c9e0f43ea9207dcb8c1f08 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Tue, 24 Oct 2023 15:30:24 +0300 Subject: [PATCH 4/9] Add new config parameter `unknown_enum_value` --- swagger_parser/README.md | 3 ++ swagger_parser/example/swagger_parser.yaml | 3 ++ .../lib/src/config/yaml_config.dart | 10 +++++ .../lib/src/generator/fill_controller.dart | 4 ++ .../lib/src/generator/generator.dart | 7 ++++ .../models/programming_language.dart | 2 + .../templates/dart_enum_dto_template.dart | 39 ++++++++++++++----- 7 files changed, 58 insertions(+), 10 deletions(-) diff --git a/swagger_parser/README.md b/swagger_parser/README.md index d5450217..9a1ce8ee 100644 --- a/swagger_parser/README.md +++ b/swagger_parser/README.md @@ -107,6 +107,9 @@ swagger_parser: # Optional. Set 'true' to set enum prefix from parent component. enums_prefix: false + # Optional (dart only). Set 'true' to maintain backwards compatibility when adding new values on the backend. + unknown_enum_value: true + # Optional. Set 'false' to not put a comment at the beginning of the generated files. mark_files_as_generated: true diff --git a/swagger_parser/example/swagger_parser.yaml b/swagger_parser/example/swagger_parser.yaml index da607fdd..f8aef017 100644 --- a/swagger_parser/example/swagger_parser.yaml +++ b/swagger_parser/example/swagger_parser.yaml @@ -58,6 +58,9 @@ swagger_parser: # Optional. Set 'true' to set enum prefix from parent component. enums_prefix: false + # Optional (dart only). Set 'true' to maintain backwards compatibility when adding new values on the backend. + unknown_enum_value: true + # Optional. Set 'false' to not put a comment at the beginning of the generated files. mark_files_as_generated: true diff --git a/swagger_parser/lib/src/config/yaml_config.dart b/swagger_parser/lib/src/config/yaml_config.dart index 2896bb2f..7557e5bc 100644 --- a/swagger_parser/lib/src/config/yaml_config.dart +++ b/swagger_parser/lib/src/config/yaml_config.dart @@ -36,6 +36,7 @@ final class YamlConfig { this.putInFolder, this.enumsToJson, this.enumsPrefix, + this.unknownEnumValue, this.markFilesAsGenerated, this.originalHttpResponse, this.replacementRules = const [], @@ -203,6 +204,13 @@ final class YamlConfig { ); } + final unknownEnumValue = yamlConfig['unknown_enum_value']; + if (unknownEnumValue is! bool?) { + throw const ConfigException( + "Config parameter 'unknown_enum_value' must be bool.", + ); + } + final markFilesAsGenerated = yamlConfig['mark_files_as_generated']; if (markFilesAsGenerated is! bool?) { throw const ConfigException( @@ -266,6 +274,7 @@ final class YamlConfig { originalHttpResponse ?? rootConfig?.originalHttpResponse, enumsToJson: enumsToJson ?? rootConfig?.enumsToJson, enumsPrefix: enumsPrefix ?? rootConfig?.enumsPrefix, + unknownEnumValue: unknownEnumValue ?? rootConfig?.unknownEnumValue, markFilesAsGenerated: markFilesAsGenerated ?? rootConfig?.markFilesAsGenerated, replacementRules: replacementRules ?? rootConfig?.replacementRules ?? [], @@ -361,6 +370,7 @@ final class YamlConfig { final bool? putInFolder; final bool? enumsToJson; final bool? enumsPrefix; + final bool? unknownEnumValue; final bool? markFilesAsGenerated; final bool? originalHttpResponse; final List replacementRules; diff --git a/swagger_parser/lib/src/generator/fill_controller.dart b/swagger_parser/lib/src/generator/fill_controller.dart index 8295c180..6e0cea9d 100644 --- a/swagger_parser/lib/src/generator/fill_controller.dart +++ b/swagger_parser/lib/src/generator/fill_controller.dart @@ -16,6 +16,7 @@ final class FillController { bool putClientsInFolder = false, bool freezed = false, bool enumsToJson = false, + bool unknownEnumValue = true, bool markFilesAsGenerated = false, }) : _openApiInfo = openApiInfo, _clientPostfix = clientPostfix, @@ -24,6 +25,7 @@ final class FillController { _putClientsInFolder = putClientsInFolder, _freezed = freezed, _enumsToJson = enumsToJson, + _unknownEnumValue = unknownEnumValue, _markFilesAsGenerated = markFilesAsGenerated; final OpenApiInfo _openApiInfo; @@ -33,6 +35,7 @@ final class FillController { final bool _freezed; final bool _putClientsInFolder; final bool _enumsToJson; + final bool _unknownEnumValue; final bool _markFilesAsGenerated; /// Return [GeneratedFile] generated from given [UniversalDataClass] @@ -44,6 +47,7 @@ final class FillController { dataClass, freezed: _freezed, enumsToJson: _enumsToJson, + unknownEnumValue: _unknownEnumValue, markFilesAsGenerated: _markFilesAsGenerated, ), ); diff --git a/swagger_parser/lib/src/generator/generator.dart b/swagger_parser/lib/src/generator/generator.dart index de3f9c10..e1e7a9cf 100644 --- a/swagger_parser/lib/src/generator/generator.dart +++ b/swagger_parser/lib/src/generator/generator.dart @@ -45,6 +45,7 @@ final class Generator { bool? putInFolder, bool? enumsToJson, bool? enumsPrefix, + bool? unknownEnumValue, bool? markFilesAsGenerated, List? replacementRules, }) : _schemaPath = schemaPath, @@ -67,6 +68,7 @@ final class Generator { _putInFolder = putInFolder ?? false, _enumsToJson = enumsToJson ?? false, _enumsPrefix = enumsPrefix ?? false, + unknownEnumValue = unknownEnumValue ?? true, _markFilesAsGenerated = markFilesAsGenerated ?? true, _replacementRules = replacementRules ?? const []; @@ -91,6 +93,7 @@ final class Generator { putInFolder: yamlConfig.putInFolder, enumsToJson: yamlConfig.enumsToJson, enumsPrefix: yamlConfig.enumsPrefix, + unknownEnumValue: yamlConfig.unknownEnumValue, markFilesAsGenerated: yamlConfig.markFilesAsGenerated, replacementRules: yamlConfig.replacementRules, ); @@ -156,6 +159,9 @@ final class Generator { /// If true, generated enums will have parent component name in its class name final bool _enumsPrefix; + /// If true, adds an unknown value for all enums to maintain backward compatibility when adding new values on the backend. + final bool unknownEnumValue; + /// If true, generated files will be marked as generated final bool _markFilesAsGenerated; @@ -293,6 +299,7 @@ final class Generator { freezed: _freezed, putClientsInFolder: _putClientsInFolder, enumsToJson: _enumsToJson, + unknownEnumValue: unknownEnumValue, markFilesAsGenerated: _markFilesAsGenerated, ); final files = []; diff --git a/swagger_parser/lib/src/generator/models/programming_language.dart b/swagger_parser/lib/src/generator/models/programming_language.dart index 8bd989ca..7b176e0b 100644 --- a/swagger_parser/lib/src/generator/models/programming_language.dart +++ b/swagger_parser/lib/src/generator/models/programming_language.dart @@ -38,6 +38,7 @@ enum ProgrammingLanguage { UniversalDataClass dataClass, { required bool freezed, required bool enumsToJson, + required bool unknownEnumValue, required bool markFilesAsGenerated, }) { switch (this) { @@ -47,6 +48,7 @@ enum ProgrammingLanguage { dataClass, freezed: freezed, enumsToJson: enumsToJson, + unknownEnumValue: unknownEnumValue, markFileAsGenerated: markFilesAsGenerated, ); } else if (dataClass is UniversalComponentClass) { diff --git a/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart b/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart index c2c9639c..41b45477 100644 --- a/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart +++ b/swagger_parser/lib/src/generator/templates/dart_enum_dto_template.dart @@ -10,9 +10,20 @@ String dartEnumDtoTemplate( UniversalEnumClass enumClass, { required bool freezed, required bool enumsToJson, + required bool unknownEnumValue, required bool markFileAsGenerated, }) { final className = enumClass.name.toPascal; + final jsonParam = unknownEnumValue || enumsToJson; + + final values = + '${enumClass.items.mapIndexed((i, e) => _enumValue(i, enumClass.type, e, jsonParam: jsonParam)).join(',\n')}${unknownEnumValue ? ',' : ';'}'; + final unkownEnumValueStr = unknownEnumValue ? _unkownEnumValue() : ''; + final constructorStr = jsonParam ? _constructor(className) : ''; + final fromJsonStr = unknownEnumValue ? _fromJson(className, enumClass) : ''; + final jsonFieldStr = jsonParam ? _jsonField(enumClass) : ''; + final toJsonStr = enumsToJson ? _toJson(enumClass, className) : ''; + return ''' ${generatedFileComment( markFileAsGenerated: markFileAsGenerated, @@ -20,31 +31,39 @@ ${generatedFileComment( ${descriptionComment(enumClass.description)}@JsonEnum() enum $className { -${enumClass.items.mapIndexed((i, e) => _enumValue(i, enumClass.type, e)).join(',\n')}, +$values$unkownEnumValueStr$constructorStr$fromJsonStr$jsonFieldStr$toJsonStr +} +'''; +} + +String _constructor(String className) => '\n\n const $className(this.json);\n'; + +String _jsonField(UniversalEnumClass enumClass) => + '\n final ${enumClass.type.toDartType()}? json;'; + +String _unkownEnumValue() => r''' + /// Default value for all unparsed values, allows backward compatibility when adding new values on the backend. - \$unknown(null); + $unknown(null);'''; - const $className(this.json); +String _fromJson(String className, UniversalEnumClass enumClass) => ''' factory $className.fromJson(${enumClass.type.toDartType()} json) => values.firstWhere( (e) => e.json == json, orElse: () => \$unknown, ); - - final ${enumClass.type.toDartType()}? json;${enumsToJson ? _toJson(enumClass, className) : ''} -} '''; -} String _enumValue( int index, String type, - UniversalEnumItem item, -) => + UniversalEnumItem item, { + required bool jsonParam, +}) => ''' ${index != 0 ? '\n' : ''}${descriptionComment(item.description, tab: ' ')} @JsonValue(${type == 'string' ? "'${item.jsonKey}'" : item.jsonKey}) - ${item.name.toCamel}(${type == 'string' ? "'${item.jsonKey}'" : item.jsonKey})'''; + ${item.name.toCamel}${jsonParam ? '(${type == 'string' ? "'${item.jsonKey}'" : item.jsonKey})' : ''}'''; String _toJson(UniversalEnumClass enumClass, String className) => '\n\n ${enumClass.type.toDartType()}? toJson() => json;'; From dac2479554e8e82181ccb0c33df4fa8033efc444 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Tue, 24 Oct 2023 15:34:12 +0300 Subject: [PATCH 5/9] 1.11.0 --- swagger_parser/CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/swagger_parser/CHANGELOG.md b/swagger_parser/CHANGELOG.md index 6ee05f58..f9290f2f 100644 --- a/swagger_parser/CHANGELOG.md +++ b/swagger_parser/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.11.0 +- Added unknown value to all enums to maintain backwards compatibility when adding new values on the backend +- Add new config parameter `unknown_enum_value` (dart only) ([#106](https://github.com/Carapacik/swagger_parser/issues/106)) + ## 1.10.5 - Fixed error with parsing dictionary objects ([#113](https://github.com/Carapacik/swagger_parser/issues/113)) @@ -5,7 +9,7 @@ - Fixed error with `additionalProperties` ([#114](https://github.com/Carapacik/swagger_parser/issues/114)) ## 1.10.3 -- Add new config parameter `original_http_response`(only for dart) ([#115](https://github.com/Carapacik/swagger_parser/issues/115)) +- Add new config parameter `original_http_response` (dart only) ([#115](https://github.com/Carapacik/swagger_parser/issues/115)) ## 1.10.2 - Fix error in `body` with name in dart template From 652455a445eae1b1dcb23cc9ab03766c7edadeb9 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Wed, 25 Oct 2023 01:43:26 +0300 Subject: [PATCH 6/9] Fix default value for enum undefined names --- swagger_parser/README.md | 3 --- .../src/generator/templates/dart_retrofit_client_template.dart | 2 +- .../generator/templates/kotlin_retrofit_client_template.dart | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/swagger_parser/README.md b/swagger_parser/README.md index 9a1ce8ee..bc7ae040 100644 --- a/swagger_parser/README.md +++ b/swagger_parser/README.md @@ -53,9 +53,6 @@ swagger_parser: # Sets the OpenApi schema path directory for api definition. schema_path: schemas/openapi.json - # Sets the url of the OpenApi schema - schema_url: https://petstore.swagger.io/v2/swagger.json - # Required. Sets output directory for generated files (Clients and DTOs). output_directory: lib/api diff --git a/swagger_parser/lib/src/generator/templates/dart_retrofit_client_template.dart b/swagger_parser/lib/src/generator/templates/dart_retrofit_client_template.dart index 87a64bb5..3991c12b 100644 --- a/swagger_parser/lib/src/generator/templates/dart_retrofit_client_template.dart +++ b/swagger_parser/lib/src/generator/templates/dart_retrofit_client_template.dart @@ -84,5 +84,5 @@ String _required(UniversalType t) => String _defaultValue(UniversalType t) => t.defaultValue != null ? ' = ' '${t.arrayDepth > 0 ? 'const ' : ''}' - '${t.enumType != null ? '${t.type}.${protectDefaultEnum(t.defaultValue)?.toCamel}' : protectDefaultValue(t.defaultValue, type: t.type)}' + '${t.enumType != null ? '${t.type}.${protectDefaultEnum(t.defaultValue?.toCamel)?.toCamel}' : protectDefaultValue(t.defaultValue, type: t.type)}' : ''; diff --git a/swagger_parser/lib/src/generator/templates/kotlin_retrofit_client_template.dart b/swagger_parser/lib/src/generator/templates/kotlin_retrofit_client_template.dart index bd4b1ead..6c5bded9 100644 --- a/swagger_parser/lib/src/generator/templates/kotlin_retrofit_client_template.dart +++ b/swagger_parser/lib/src/generator/templates/kotlin_retrofit_client_template.dart @@ -67,5 +67,5 @@ String _toQueryParameter(UniversalRequestType parameter) => /// return defaultValue if have String _defaultValue(UniversalType t) => t.defaultValue != null ? ' = ' - '${t.enumType != null ? '${t.type}.${protectDefaultEnum(t.defaultValue)?.toScreamingSnake}' : protectDefaultValue(t.defaultValue, type: t.type, dart: false)}' + '${t.enumType != null ? '${t.type}.${protectDefaultEnum(t.defaultValue?.toScreamingSnake)?.toScreamingSnake}' : protectDefaultValue(t.defaultValue, type: t.type, dart: false)}' : ''; From 1d01d0162c3d0cddf9374aad360efdc5ab0c3d52 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Thu, 26 Oct 2023 02:03:14 +0300 Subject: [PATCH 7/9] Fix tests --- .../test/generator/data_classes_test.dart | 179 ++++++++++++------ 1 file changed, 120 insertions(+), 59 deletions(-) diff --git a/swagger_parser/test/generator/data_classes_test.dart b/swagger_parser/test/generator/data_classes_test.dart index 65a3d457..226073dd 100644 --- a/swagger_parser/test/generator/data_classes_test.dart +++ b/swagger_parser/test/generator/data_classes_test.dart @@ -1097,7 +1097,7 @@ class ClassName with _$ClassName { ), ]; - const fillController = FillController(); + const fillController = FillController(unknownEnumValue: false); final files = []; for (final enumClass in dataClasses) { files.add(fillController.fillDtoContent(enumClass)); @@ -1109,8 +1109,10 @@ import 'package:json_annotation/json_annotation.dart'; enum EnumName { @JsonValue(1) value1, + @JsonValue(2) value2, + @JsonValue(3) value3; } @@ -1123,10 +1125,13 @@ import 'package:json_annotation/json_annotation.dart'; enum EnumNameString { @JsonValue('itemOne') itemOne, + @JsonValue('ItemTwo') itemTwo, + @JsonValue('item_three') itemThree, + @JsonValue('ITEM-FOUR') itemFour, @@ -1161,10 +1166,13 @@ import 'package:json_annotation/json_annotation.dart'; enum EnumNameStringWithLeadingNumbers { @JsonValue('1itemOne') value1itemOne, + @JsonValue('2ItemTwo') value2ItemTwo, + @JsonValue('3item_three') value3itemThree, + @JsonValue('4ITEM-FOUR') value4ItemFour, @@ -1196,56 +1204,57 @@ enum EnumNameStringWithLeadingNumbers { ), ]; - const fillController = FillController(enumsToJson: true); + const fillController = + FillController(enumsToJson: true, unknownEnumValue: false); final files = []; for (final enumClass in dataClasses) { files.add(fillController.fillDtoContent(enumClass)); } - const expectedContent0 = r''' + const expectedContent0 = ''' import 'package:json_annotation/json_annotation.dart'; @JsonEnum() enum EnumName { @JsonValue(1) - value1, + value1(1), + @JsonValue(2) - value2, + value2(2), + @JsonValue(3) - value3; + value3(3); - int toJson() => _$EnumNameEnumMap[this]!; -} + const EnumName(this.json); + + final int? json; -const _$EnumNameEnumMap = { - EnumName.value1: 1, - EnumName.value2: 2, - EnumName.value3: 3, -}; + int? toJson() => json; +} '''; - const expectedContent1 = r''' + const expectedContent1 = ''' import 'package:json_annotation/json_annotation.dart'; @JsonEnum() enum EnumNameString { @JsonValue('itemOne') - itemOne, + itemOne('itemOne'), + @JsonValue('ItemTwo') - itemTwo, + itemTwo('ItemTwo'), + @JsonValue('item_three') - itemThree, + itemThree('item_three'), + @JsonValue('ITEM-FOUR') - itemFour; + itemFour('ITEM-FOUR'); - String toJson() => _$EnumNameStringEnumMap[this]!; -} + const EnumNameString(this.json); -const _$EnumNameStringEnumMap = { - EnumNameString.itemOne: 'itemOne', - EnumNameString.itemTwo: 'ItemTwo', - EnumNameString.itemThree: 'item_three', - EnumNameString.itemFour: 'ITEM-FOUR', -}; + final String? json; + + String? toJson() => json; +} '''; expect(files[0].contents, expectedContent0); @@ -1274,7 +1283,8 @@ const _$EnumNameStringEnumMap = { items: UniversalEnumItem.listFromNames({'FALSE', 'for', 'do'}), ), ]; - const fillController = FillController(freezed: true); + const fillController = + FillController(freezed: true, unknownEnumValue: false); final files = []; for (final enumClass in dataClasses) { files.add(fillController.fillDtoContent(enumClass)); @@ -1286,8 +1296,10 @@ import 'package:freezed_annotation/freezed_annotation.dart'; enum EnumName { @JsonValue(1) value1, + @JsonValue(2) value2, + @JsonValue(3) value3; } @@ -1300,10 +1312,13 @@ import 'package:freezed_annotation/freezed_annotation.dart'; enum EnumNameString { @JsonValue('itemOne') itemOne, + @JsonValue('ItemTwo') itemTwo, + @JsonValue('item_three') itemThree, + @JsonValue('ITEM-FOUR') itemFour; } @@ -1358,20 +1373,28 @@ import 'package:freezed_annotation/freezed_annotation.dart'; @JsonEnum() enum EnumName { @JsonValue(1) - value1, + value1(1), + @JsonValue(2) - value2, + value2(2), + @JsonValue(3) - value3; + value3(3), - int toJson() => _$EnumNameEnumMap[this]!; -} + /// Default value for all unparsed values, allows backward compatibility when adding new values on the backend. + $unknown(null); + + const EnumName(this.json); + + factory EnumName.fromJson(int json) => values.firstWhere( + (e) => e.json == json, + orElse: () => $unknown, + ); -const _$EnumNameEnumMap = { - EnumName.value1: 1, - EnumName.value2: 2, - EnumName.value3: 3, -}; + final int? json; + + int? toJson() => json; +} '''; const expectedContent1 = r''' @@ -1380,23 +1403,31 @@ import 'package:freezed_annotation/freezed_annotation.dart'; @JsonEnum() enum EnumNameString { @JsonValue('itemOne') - itemOne, + itemOne('itemOne'), + @JsonValue('ItemTwo') - itemTwo, + itemTwo('ItemTwo'), + @JsonValue('item_three') - itemThree, + itemThree('item_three'), + @JsonValue('ITEM-FOUR') - itemFour; + itemFour('ITEM-FOUR'), - String toJson() => _$EnumNameStringEnumMap[this]!; -} + /// Default value for all unparsed values, allows backward compatibility when adding new values on the backend. + $unknown(null); + + const EnumNameString(this.json); + + factory EnumNameString.fromJson(String json) => values.firstWhere( + (e) => e.json == json, + orElse: () => $unknown, + ); + + final String? json; -const _$EnumNameStringEnumMap = { - EnumNameString.itemOne: 'itemOne', - EnumNameString.itemTwo: 'ItemTwo', - EnumNameString.itemThree: 'item_three', - EnumNameString.itemFour: 'ITEM-FOUR', -}; + String? toJson() => json; +} '''; expect(files[0].contents, expectedContent0); expect(files[1].contents, expectedContent1); @@ -1495,19 +1526,34 @@ enum class KeywordsName { const fillController = FillController(); final file = fillController.fillDtoContent(dataClass); - const expectedContent = ''' + const expectedContent = r''' import 'package:json_annotation/json_annotation.dart'; @JsonEnum() enum EnumName { @JsonValue(-2) - valueMinus2, + valueMinus2(-2), + @JsonValue(-1) - valueMinus1, + valueMinus1(-1), + @JsonValue(0) - value0, + value0(0), + @JsonValue(1) - value1; + value1(1), + + /// Default value for all unparsed values, allows backward compatibility when adding new values on the backend. + $unknown(null); + + const EnumName(this.json); + + factory EnumName.fromJson(int json) => values.firstWhere( + (e) => e.json == json, + orElse: () => $unknown, + ); + + final int? json; } '''; @@ -1523,19 +1569,34 @@ enum EnumName { const fillController = FillController(freezed: true); final file = fillController.fillDtoContent(dataClass); - const expectedContent = ''' + const expectedContent = r''' import 'package:freezed_annotation/freezed_annotation.dart'; @JsonEnum() enum EnumName { @JsonValue(-2) - valueMinus2, + valueMinus2(-2), + @JsonValue(-1) - valueMinus1, + valueMinus1(-1), + @JsonValue(0) - value0, + value0(0), + @JsonValue(1) - value1; + value1(1), + + /// Default value for all unparsed values, allows backward compatibility when adding new values on the backend. + $unknown(null); + + const EnumName(this.json); + + factory EnumName.fromJson(int json) => values.firstWhere( + (e) => e.json == json, + orElse: () => $unknown, + ); + + final int? json; } '''; From 86f17757a8ca8372a764907bc151dc1aee265b9f Mon Sep 17 00:00:00 2001 From: StarProxima Date: Thu, 26 Oct 2023 02:10:05 +0300 Subject: [PATCH 8/9] #127 --- swagger_parser/CHANGELOG.md | 1 + swagger_parser/lib/src/utils/type_utils.dart | 2 +- swagger_parser/test/generator/data_classes_test.dart | 11 +++++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/swagger_parser/CHANGELOG.md b/swagger_parser/CHANGELOG.md index b7c6b954..c632ef6a 100644 --- a/swagger_parser/CHANGELOG.md +++ b/swagger_parser/CHANGELOG.md @@ -1,6 +1,7 @@ ## 1.11.0 - Added unknown value to all enums to maintain backwards compatibility when adding new values on the backend - Add new config parameter `unknown_enum_value` (dart only) ([#106](https://github.com/Carapacik/swagger_parser/issues/106)) +- Support String values with spaces for enums ([#127](https://github.com/Carapacik/swagger_parser/issues/127)) ## 1.10.6 - Fixed map objects parsing as separate entities ([#124](https://github.com/Carapacik/swagger_parser/issues/124)) diff --git a/swagger_parser/lib/src/utils/type_utils.dart b/swagger_parser/lib/src/utils/type_utils.dart index 9719a9a1..da25cbbb 100644 --- a/swagger_parser/lib/src/utils/type_utils.dart +++ b/swagger_parser/lib/src/utils/type_utils.dart @@ -61,7 +61,7 @@ String uniqueName({bool isEnum = false}) { return name; } -final _enumNameRegExp = RegExp(r'^[a-zA-Z\d_-]*$'); +final _enumNameRegExp = RegExp(r'^[a-zA-Z\d_-\s]*$'); final _startWithNumberRegExp = RegExp(r'^-?\d+'); /// Protect default enum value from incorrect symbols, keywords, etc. diff --git a/swagger_parser/test/generator/data_classes_test.dart b/swagger_parser/test/generator/data_classes_test.dart index 226073dd..50d420fb 100644 --- a/swagger_parser/test/generator/data_classes_test.dart +++ b/swagger_parser/test/generator/data_classes_test.dart @@ -1092,6 +1092,7 @@ class ClassName with _$ClassName { '3item_three', '4ITEM-FOUR', '5иллегалчарактер', + '6 item six', }, ), ), @@ -1178,7 +1179,10 @@ enum EnumNameStringWithLeadingNumbers { /// Incorrect name has been replaced. Original name: `5иллегалчарактер`. @JsonValue('5иллегалчарактер') - undefined0; + undefined0, + + @JsonValue('6 item six') + value6ItemSix; } '''; @@ -1357,7 +1361,7 @@ enum KeywordsName { name: 'EnumNameString', type: 'string', items: UniversalEnumItem.listFromNames( - {'itemOne', 'ItemTwo', 'item_three', 'ITEM-FOUR'}, + {'itemOne', 'ItemTwo', 'item_three', 'ITEM-FOUR', 'Item five'}, ), ), ]; @@ -1414,6 +1418,9 @@ enum EnumNameString { @JsonValue('ITEM-FOUR') itemFour('ITEM-FOUR'), + @JsonValue('Item five') + itemFive('Item five'), + /// Default value for all unparsed values, allows backward compatibility when adding new values on the backend. $unknown(null); From 48f901084cd619bbaff9c201a6e196eb32c6d164 Mon Sep 17 00:00:00 2001 From: StarProxima Date: Thu, 26 Oct 2023 12:46:54 +0300 Subject: [PATCH 9/9] Update README.md --- swagger_parser/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/swagger_parser/README.md b/swagger_parser/README.md index bc7ae040..86ea3908 100644 --- a/swagger_parser/README.md +++ b/swagger_parser/README.md @@ -53,6 +53,9 @@ swagger_parser: # Sets the OpenApi schema path directory for api definition. schema_path: schemas/openapi.json + # Sets the url of the OpenApi schema + schema_url: https://petstore.swagger.io/v2/swagger.json + # Required. Sets output directory for generated files (Clients and DTOs). output_directory: lib/api