diff --git a/.github/workflows/samples-dart-freezed.yaml b/.github/workflows/samples-dart-freezed.yaml
new file mode 100644
index 000000000000..4b66b55e5007
--- /dev/null
+++ b/.github/workflows/samples-dart-freezed.yaml
@@ -0,0 +1,39 @@
+name: Samples Dart
+
+on:
+ push:
+ branches:
+ - master
+ - '[5-9]+.[0-9]+.x'
+ pull_request:
+ branches:
+ - master
+ - '[5-9]+.[0-9]+.x'
+ paths:
+ - 'samples/openapi3/client/petstore/dart*/freezed'
+
+jobs:
+ tests-dart:
+ name: Tests Dart
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-java@v4
+ with:
+ distribution: 'temurin'
+ java-version: 11
+ cache: maven
+ - name: Cache test dependencies
+ uses: actions/cache@v4
+ env:
+ cache-name: pub-cache
+ with:
+ path: $PUB_CACHE
+ key: ${{ runner.os }}-${{ github.job }}-${{ env.cache-name }}-${{ hashFiles('samples/**/pubspec.*') }}
+ - uses: dart-lang/setup-dart@v1
+ with:
+ sdk: 3.0.0
+ - name: Run tests
+ uses: ./.github/actions/run-samples
+ with:
+ name: samples.dart
diff --git a/.github/workflows/samples-dart.yaml b/.github/workflows/samples-dart.yaml
index aeb5637634d1..21dd560615bf 100644
--- a/.github/workflows/samples-dart.yaml
+++ b/.github/workflows/samples-dart.yaml
@@ -11,6 +11,8 @@ on:
- '[5-9]+.[0-9]+.x'
paths:
- 'samples/openapi3/client/petstore/dart*/**'
+ - '!samples/openapi3/client/petstore/dart*/freezed'
+
jobs:
tests-dart:
diff --git a/bin/configs/dart-dio-oneof-freezed.yaml b/bin/configs/dart-dio-oneof-freezed.yaml
new file mode 100644
index 000000000000..7c2baeb15adf
--- /dev/null
+++ b/bin/configs/dart-dio-oneof-freezed.yaml
@@ -0,0 +1,12 @@
+generatorName: dart-dio
+outputDir: samples/openapi3/client/petstore/dart-dio/freezed/oneof
+inputSpec: modules/openapi-generator/src/test/resources/3_0/oneOf.yaml
+templateDir: modules/openapi-generator/src/main/resources/dart/libraries/dio
+typeMappings:
+ Client: "ModelClient"
+ File: "ModelFile"
+ EnumClass: "ModelEnumClass"
+additionalProperties:
+ hideGenerationTimestamp: "true"
+ serializationLibrary: "freezed"
+
diff --git a/bin/configs/dart-dio-oneof-polymorphism-and-inheritance-freezed.yaml b/bin/configs/dart-dio-oneof-polymorphism-and-inheritance-freezed.yaml
new file mode 100644
index 000000000000..df67bb1d13c2
--- /dev/null
+++ b/bin/configs/dart-dio-oneof-polymorphism-and-inheritance-freezed.yaml
@@ -0,0 +1,12 @@
+generatorName: dart-dio
+outputDir: samples/openapi3/client/petstore/dart-dio/freezed/oneof_polymorphism_and_inheritance
+inputSpec: modules/openapi-generator/src/test/resources/3_0/oneof_polymorphism_and_inheritance.yaml
+templateDir: modules/openapi-generator/src/main/resources/dart/libraries/dio
+typeMappings:
+ Client: "ModelClient"
+ File: "ModelFile"
+ EnumClass: "ModelEnumClass"
+additionalProperties:
+ hideGenerationTimestamp: "true"
+ enumUnknownDefaultCase: "true"
+ serializationLibrary: "freezed"
diff --git a/bin/configs/dart-dio-oneof-primitive-freezed.yaml b/bin/configs/dart-dio-oneof-primitive-freezed.yaml
new file mode 100644
index 000000000000..a2c948ebe086
--- /dev/null
+++ b/bin/configs/dart-dio-oneof-primitive-freezed.yaml
@@ -0,0 +1,12 @@
+generatorName: dart-dio
+outputDir: samples/openapi3/client/petstore/dart-dio/freezed/oneof_primitive
+inputSpec: modules/openapi-generator/src/test/resources/3_0/oneOf_primitive.yaml
+templateDir: modules/openapi-generator/src/main/resources/dart/libraries/dio
+typeMappings:
+ Client: "ModelClient"
+ File: "ModelFile"
+ EnumClass: "ModelEnumClass"
+additionalProperties:
+ hideGenerationTimestamp: "true"
+ enumUnknownDefaultCase: "true"
+ serializationLibrary: "freezed"
diff --git a/bin/configs/dart-dio-petstore-client-lib-fake-freezed.yaml b/bin/configs/dart-dio-petstore-client-lib-fake-freezed.yaml
new file mode 100644
index 000000000000..82723cd9c2d1
--- /dev/null
+++ b/bin/configs/dart-dio-petstore-client-lib-fake-freezed.yaml
@@ -0,0 +1,12 @@
+generatorName: dart-dio
+outputDir: samples/openapi3/client/petstore/dart-dio/freezed/petstore_client_lib_fake
+inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
+templateDir: modules/openapi-generator/src/main/resources/dart/libraries/dio
+typeMappings:
+ Client: "ModelClient"
+ File: "ModelFile"
+ EnumClass: "ModelEnumClass"
+additionalProperties:
+ hideGenerationTimestamp: "true"
+ enumUnknownDefaultCase: "true"
+ serializationLibrary: "freezed"
diff --git a/docs/generators/dart-dio.md b/docs/generators/dart-dio.md
index 7e62f92f0782..2521ce07e7fd 100644
--- a/docs/generators/dart-dio.md
+++ b/docs/generators/dart-dio.md
@@ -36,7 +36,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|pubPublishTo|Publish_to in generated pubspec| |null|
|pubRepository|Repository in generated pubspec| |null|
|pubVersion|Version in generated pubspec| |1.0.0|
-|serializationLibrary|Specify serialization library|
- **built_value**
- [DEFAULT] built_value
- **json_serializable**
- [BETA] json_serializable
|built_value|
+|serializationLibrary|Specify serialization library|- **built_value**
- [DEFAULT] built_value
- **json_serializable**
- [BETA] json_serializable
- **freezed**
- [BETA] freezed
|built_value|
|skipCopyWith|Skip CopyWith when using Json Serializable for serialization| |false|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java
index d9d038746372..0bc43f7ef953 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java
@@ -24,6 +24,7 @@
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.CodegenDiscriminator.MappedModel;
import org.openapitools.codegen.api.TemplatePathLocator;
@@ -49,6 +50,8 @@
import java.util.*;
import java.util.stream.Collectors;
+import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER;
+import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
public class DartDioClientCodegen extends AbstractDartCodegen {
@@ -65,6 +68,8 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
public static final String EQUALITY_CHECK_METHOD_EQUATABLE = "equatable";
public static final String SERIALIZATION_LIBRARY_BUILT_VALUE = "built_value";
public static final String SERIALIZATION_LIBRARY_JSON_SERIALIZABLE = "json_serializable";
+
+ public static final String SERIALIZATION_LIBRARY_FREEZED = "freezed";
public static final String SERIALIZATION_LIBRARY_DEFAULT = SERIALIZATION_LIBRARY_BUILT_VALUE;
private static final String DIO_IMPORT = "package:dio/dio.dart";
@@ -74,6 +79,7 @@ public class DartDioClientCodegen extends AbstractDartCodegen {
public static final String SKIP_COPY_WITH_DEFAULT_VALUE = "false";
private static final String CLIENT_NAME = "clientName";
+ private static final String FREEZED_UNION_RESPONSE = "freezedUnionResponse";
@Getter @Setter
private String dateLibrary;
@@ -111,6 +117,7 @@ public DartDioClientCodegen() {
supportedLibraries.put(SERIALIZATION_LIBRARY_BUILT_VALUE, "[DEFAULT] built_value");
supportedLibraries.put(SERIALIZATION_LIBRARY_JSON_SERIALIZABLE, "[BETA] json_serializable");
+ supportedLibraries.put(SERIALIZATION_LIBRARY_FREEZED, "[BETA] freezed");
final CliOption serializationLibrary = CliOption.newString(CodegenConstants.SERIALIZATION_LIBRARY, "Specify serialization library");
serializationLibrary.setEnum(supportedLibraries);
serializationLibrary.setDefault(SERIALIZATION_LIBRARY_DEFAULT);
@@ -231,6 +238,10 @@ private void configureSerializationLibrary(String srcFolder) {
additionalProperties.put("useJsonSerializable", "true");
configureSerializationLibraryJsonSerializable(srcFolder);
break;
+ case SERIALIZATION_LIBRARY_FREEZED:
+ additionalProperties.put("useFreezed", "true");
+ configureSerializationLibraryFreezed(srcFolder);
+ break;
default:
case SERIALIZATION_LIBRARY_BUILT_VALUE:
additionalProperties.put("useBuiltValue", "true");
@@ -306,6 +317,94 @@ private void configureEqualityCheckMethod(String srcFolder) {
}
}
+ private void configureSerializationLibraryFreezed(String srcFolder) {
+ if (!additionalProperties.containsKey(FREEZED_UNION_RESPONSE)) {
+ additionalProperties.put(FREEZED_UNION_RESPONSE, false);
+ LOGGER.debug("freezedUnionResponse not set, using default {}", false);
+ }
+ supportingFiles.add(new SupportingFile("serialization/freezed/build.yaml.mustache", "" /* main project dir */, "build.yaml"));
+ supportingFiles.add(new SupportingFile("serialization/freezed/models.dart.mustache", srcFolder + File.separator + modelPackage, "models.dart"));
+ supportingFiles.add(new SupportingFile("serialization/freezed/primitive_union_types.mustache", srcFolder + File.separator + modelPackage, "primitive_union_types.dart"));
+ if(((boolean) additionalProperties.getOrDefault(FREEZED_UNION_RESPONSE, false))){
+ supportingFiles.add(new SupportingFile("serialization/freezed/response_models.mustache", srcFolder + File.separator + modelPackage, "response_models.dart"));
+ }
+ // most of these are defined in AbstractDartCodegen, we are overriding
+ // just the binary / file handling
+ languageSpecificPrimitives.add("Object");
+ imports.put("Uint8List", "dart:typed_data");
+ imports.put("MultipartFile", DIO_IMPORT);
+ // A lambda which removes the model name prefix and suffix. Used mainly for default descrimator class name
+ // mapping in fromJson methods for unions in freezed.
+ additionalProperties.put("DelModelNamePrefixSuffix", (Mustache.Lambda) (fragment, writer) -> {
+ String content = fragment.execute();
+ content = content.trim().replaceAll("\n", "");
+ content = content.replaceAll(this.modelNamePrefix, "");
+ content = content.replaceAll(this.modelNameSuffix, "");
+ writer.write(content);
+ });
+ // A lambda which transforms Types for naming factory constructors inFreezed unions.
+ additionalProperties.put("PrimitiveInUnion", (Mustache.Lambda) (fragment, writer) -> {
+ String content = fragment.execute();
+ content = content.trim().replaceAll("\n", "");
+ Set collectionTypes = Sets.newHashSet("List","Map","Set");
+ Set nonCollectionTypes = defaultIncludes.stream().filter(e -> !collectionTypes.contains(e)).collect(Collectors.toSet());
+ if(nonCollectionTypes.contains(content)){
+ writer.write(content + "InUnion");
+ return;
+ }
+ writer.write(content);
+ });
+ // A lambda to generate correct form of FromJson methods.
+ additionalProperties.put("PrimitiveFromJson", (Mustache.Lambda) (fragment, writer) -> {
+ String content = fragment.execute();
+ content = content.trim().replaceAll("\n", "");
+ // Remove Generics Declarations as this is not required for factoryNames in freezed
+ String tmp_1 = StringUtils.substringBefore(content, "<");
+ if(defaultIncludes.contains(tmp_1)) {
+ if (tmp_1.equals("Set") || tmp_1.equals("Map")) {
+ content = "<"+StringUtils.substringAfter(content, "<")+"{}";
+ }else if(tmp_1.equals("List")){
+ content = "<"+StringUtils.substringAfter(content, "<")+"[]";
+ }else{
+ content = tmp_1+"InUnion";
+ }
+ }
+ writer.write(content);
+ });
+ // A lambda to filter out collection types from anyOf and oneOf sets in codegenmodel.
+ additionalProperties.put("PrimitiveCollectionsExtension", (Mustache.Lambda) (fragment, writer) -> {
+ String content = fragment.execute();
+ content = content.trim().replaceAll("\n", "");
+ Set collectionTypes = Sets.newHashSet("List","Map","Set");
+ // Remove Generics Declarations as this is not required for factoryNames in freezed
+ String tmp_1 = StringUtils.substringBefore(content, "<");
+ if(collectionTypes.contains(tmp_1)){
+ String variableName = camelize(fragment.execute().replace(" ", "_"), LOWERCASE_FIRST_LETTER);
+ variableName = this.sanitizeName(variableName);
+ if (this.reservedWords().contains(variableName)) {
+ // Escaping must be done *after* camelize, because generators may escape using characters removed by camelize function.
+ variableName = this.escapeReservedWord(variableName);
+ }
+ tmp_1 = String.join("\n", "extension on "+ content + "{",
+ "dynamic fromJson(Map json) {",
+ "return json[\""+variableName+"Value\"];",
+ "}",
+
+ "Map toJson() {",
+ "return {",
+ "\""+variableName+"Value\": this,",
+ "};",
+ "}",
+ "}");
+ writer.write(tmp_1);
+ }else{
+ writer.write("");
+
+ }
+ });
+
+ }
+
private void configureDateLibrary(String srcFolder) {
switch (dateLibrary) {
case DATE_LIBRARY_TIME_MACHINE:
@@ -602,7 +701,7 @@ protected CodegenDiscriminator createDiscriminator(String schemaName, Schema sch
@Override
public Map postProcessAllModels(Map objs) {
objs = super.postProcessAllModels(objs);
- if (SERIALIZATION_LIBRARY_BUILT_VALUE.equals(library)) {
+ if (SERIALIZATION_LIBRARY_BUILT_VALUE.equals(library) || SERIALIZATION_LIBRARY_FREEZED.equals(library)) {
adaptToDartInheritance(objs);
syncRootTypesWithInnerVars(objs);
}
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/analysis_options.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/analysis_options.mustache
index b625c648d600..c8420bea2674 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/analysis_options.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/analysis_options.mustache
@@ -6,5 +6,9 @@ analyzer:
exclude:
- test/*.dart{{#useJsonSerializable}}
- lib/{{sourceFolder}}/model/*.g.dart{{/useJsonSerializable}}
+ {{#useFreezed}}
+ - lib/src/model/*.g.dart
+ - lib/src/model/*.freezed.dart
+ {{/useFreezed}}
errors:
deprecated_member_use_from_same_package: ignore
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache
index e86a2cfb005a..97ae46a17dec 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache
@@ -5,8 +5,12 @@ import 'dart:async';
import 'package:dio/dio.dart';
{{#operations}}
-{{#imports}}import '{{.}}';
-{{/imports}}
+{{! No need to Import all the required model files as freezed uses the part of directive for it models}}
+{{^useFreezed}}
+ {{#imports}}
+import '{{.}}';
+ {{/imports}}
+{{/useFreezed}}
class {{classname}} {
@@ -38,7 +42,16 @@ class {{classname}} {
{{#isDeprecated}}
@Deprecated('This operation has been deprecated')
{{/isDeprecated}}
- Future> {{nickname}}({ {{#allParams}}{{#isPathParam}}
+ {{#useFreezed}}
+ {{#freezedUnionResponse}}
+ Future> {{nickname}}({
+ {{/freezedUnionResponse}}
+ {{^freezedUnionResponse}}
+ Future> {{nickname}}({
+ {{/freezedUnionResponse}}
+ {{/useFreezed}}
+ {{^useFreezed}}
+ Future> {{nickname}}({ {{/useFreezed}}{{#allParams}}{{#isPathParam}}
{{#isDeprecated}}@Deprecated('{{paramName}} is deprecated') {{/isDeprecated}}required {{{dataType}}} {{paramName}},{{/isPathParam}}{{#isQueryParam}}
{{#isDeprecated}}@Deprecated('{{paramName}} is deprecated') {{/isDeprecated}}{{#required}}{{^isNullable}}{{^defaultValue}}required {{/defaultValue}}{{/isNullable}}{{/required}}{{{dataType}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}} {{paramName}}{{^isContainer}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isContainer}},{{/isQueryParam}}{{#isHeaderParam}}
{{#isDeprecated}}@Deprecated('{{paramName}} is deprecated') {{/isDeprecated}}{{#required}}{{^isNullable}}{{^defaultValue}}required {{/defaultValue}}{{/isNullable}}{{/required}}{{{dataType}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}} {{paramName}}{{^isContainer}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{/isContainer}},{{/isHeaderParam}}{{#isBodyParam}}
@@ -116,7 +129,15 @@ class {{classname}} {
);
{{#returnType}}
- {{{.}}}? _responseData;
+ {{#useFreezed}}
+ {{#freezedUnionResponse}}
+ {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Data _responseData;
+ {{/freezedUnionResponse}}
+ {{^freezedUnionResponse}}
+ {{{returnType}}} _responseData;
+ {{/freezedUnionResponse}}
+ {{/useFreezed}}
+ {{^useFreezed}}{{{.}}}? _responseData;{{/useFreezed}}
try {
{{#includeLibraryTemplate}}api/deserialize{{/includeLibraryTemplate}}
@@ -130,7 +151,17 @@ class {{classname}} {
);
}
+ {{#useFreezed}}
+ {{#freezedUnionResponse}}
+ return Response<{{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Data>(
+ {{/freezedUnionResponse}}
+ {{^freezedUnionResponse}}
return Response<{{{returnType}}}>(
+ {{/freezedUnionResponse}}
+ {{/useFreezed}}
+ {{^useFreezed}}
+ return Response<{{{returnType}}}>(
+ {{/useFreezed}}
data: _responseData,
headers: _response.headers,
isRedirect: _response.isRedirect,
@@ -139,8 +170,41 @@ class {{classname}} {
statusCode: _response.statusCode,
statusMessage: _response.statusMessage,
extra: _response.extra,
- );{{/returnType}}{{^returnType}}
- return _response;{{/returnType}}
+ );{{/returnType}}
+ {{^returnType}}
+ {{^useFreezed}}
+ return _response;
+ {{/useFreezed}}
+ {{#useFreezed}}
+ {{#freezedUnionResponse}}
+ {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Data _responseData;
+ try {
+ {{#includeLibraryTemplate}}api/deserialize{{/includeLibraryTemplate}}
+ } catch (error, stackTrace) {
+ throw DioException(
+ requestOptions: _response.requestOptions,
+ response: _response,
+ type: DioExceptionType.unknown,
+ error: error,
+ stackTrace: stackTrace,
+ );
+ }
+ return Response<{{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Data>(
+ data: _responseData,
+ headers: _response.headers,
+ isRedirect: _response.isRedirect,
+ requestOptions: _response.requestOptions,
+ redirects: _response.redirects,
+ statusCode: _response.statusCode,
+ statusMessage: _response.statusMessage,
+ extra: _response.extra,
+ );
+ {{/freezedUnionResponse}}
+ {{^freezedUnionResponse}}
+ return _response;
+ {{/freezedUnionResponse}}
+ {{/useFreezed}}
+ {{/returnType}}
}
{{/operation}}
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/lib.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/lib.mustache
index 63b1ce28e031..0205ed40b85e 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/lib.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/lib.mustache
@@ -9,5 +9,6 @@ export 'package:{{pubName}}/{{sourceFolder}}/auth/oauth.dart';
{{#apiInfo}}{{#apis}}export 'package:{{pubName}}/{{sourceFolder}}/{{apiPackage}}/{{classFilename}}.dart';
{{/apis}}{{/apiInfo}}
-{{#models}}{{#model}}export 'package:{{pubName}}/{{sourceFolder}}/{{modelPackage}}/{{classFilename}}.dart';
-{{/model}}{{/models}}
+{{^useFreezed}}{{#models}}{{#model}}export 'package:{{pubName}}/{{sourceFolder}}/{{modelPackage}}/{{classFilename}}.dart';
+{{/model}}{{/models}}{{/useFreezed}}
+{{#useFreezed}}export 'package:{{pubName}}/{{sourceFolder}}/{{modelPackage}}/models.dart';{{/useFreezed}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/model.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/model.mustache
index 1917decaf6c6..6a9561375b01 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/model.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/model.mustache
@@ -1,10 +1,12 @@
{{>header}}
-// ignore_for_file: unused_element
+// ignore_for_file: unused_element{{#useFreezed}}, invalid_annotation_target{{/useFreezed}}
{{#models}}
{{#model}}
+ {{^useFreezed}}
{{#imports}}
import '{{.}}';
{{/imports}}
+ {{/useFreezed}}
{{#isEnum}}{{>enum}}{{/isEnum}}{{^isEnum}}{{>class}}{{/isEnum}}
{{/model}}
{{/models}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache
index b0ac707ecee7..0dad3bd86546 100644
--- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/pubspec.mustache
@@ -11,7 +11,12 @@ publish_to: {{.}}
environment:
+ {{^useFreezed}}
sdk: '>={{^useJsonSerializable}}2.18.0{{/useJsonSerializable}}{{#useJsonSerializable}}3.5.0{{/useJsonSerializable}} <4.0.0'
+ {{/useFreezed}}
+ {{#useFreezed}}
+ sdk: '^3.0.0'
+ {{/useFreezed}}
dependencies:
dio: '^5.7.0'
@@ -30,6 +35,10 @@ dependencies:
{{/skipCopyWith}}
json_annotation: '^4.9.0'
{{/useJsonSerializable}}
+{{#useFreezed}}
+ freezed_annotation: '^2.4.4'
+ json_annotation: '^4.9.0'
+{{/useFreezed}}
{{#useDateLibTimeMachine}}
time_machine: ^0.9.17
{{/useDateLibTimeMachine}}
@@ -46,4 +55,9 @@ dev_dependencies:
{{/skipCopyWith}}
json_serializable: '^6.9.3'
{{/useJsonSerializable}}
+{{#useFreezed}}
+ freezed: '^2.5.2'
+ json_serializable: '^6.8.0'
+ build_runner: any
+{{/useFreezed}}
test: '^1.16.0'
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/case_parse_json_using_discriminator_mapping_value.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/case_parse_json_using_discriminator_mapping_value.mustache
new file mode 100644
index 000000000000..0c4e371b60ca
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/case_parse_json_using_discriminator_mapping_value.mustache
@@ -0,0 +1,6 @@
+{{#mappedModels}}
+ case '{{mappingName}}':
+ return {{classname}}.as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{modelName}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}(
+ {{#lambda.camelcase}}{{modelName}}{{/lambda.camelcase}}Value : {{modelName}}.fromJson(json),
+ );
+{{/mappedModels}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/case_parse_json_using_model_name.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/case_parse_json_using_model_name.mustache
new file mode 100644
index 000000000000..96711921f042
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/case_parse_json_using_model_name.mustache
@@ -0,0 +1,14 @@
+{{#anyOf}}
+ case '{{#DelModelNamePrefixSuffix}}{{{.}}}{{/DelModelNamePrefixSuffix}}':
+ deserializedModel = {{classname}}.as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}(
+ {{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}Value : {{#lambda.titlecase}}{{#PrimitiveInUnion}}{{{.}}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}.fromJson(json),
+ );
+ break;
+{{/anyOf}}
+{{#oneOf}}
+ case '{{#DelModelNamePrefixSuffix}}{{{.}}}{{/DelModelNamePrefixSuffix}}':
+ deserializedModel = {{classname}}.as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}(
+ {{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}Value : {{#lambda.titlecase}}{{#PrimitiveInUnion}}{{{.}}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}.fromJson(json),
+ );
+ break;
+{{/oneOf}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/freezed_union_for_oneof_anyof.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/freezed_union_for_oneof_anyof.mustache
new file mode 100644
index 000000000000..c7bb47d453a0
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/freezed_union_for_oneof_anyof.mustache
@@ -0,0 +1,38 @@
+@freezed
+sealed class {{classname}} with _${{classname}} {
+const {{classname}}._();
+
+{{#anyOf}}
+ const factory {{classname}}.as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}({
+ required {{#lambda.titlecase}}{{#PrimitiveInUnion}}{{{.}}}{{/PrimitiveInUnion}}{{/lambda.titlecase}} {{#lambda.camelcase}}{{{.}}}Value{{/lambda.camelcase}}
+ }) = {{classname}}As{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}};
+{{/anyOf}}
+{{#oneOf}}
+ const factory {{classname}}.as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}({
+ required {{#lambda.titlecase}}{{#PrimitiveInUnion}}{{{.}}}{{/PrimitiveInUnion}}{{/lambda.titlecase}} {{#lambda.camelcase}}{{{.}}}Value{{/lambda.camelcase}}
+ }) = {{classname}}As{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}};
+{{/oneOf}}
+{{! Sometimes discrintors are mentioned in parent classes}}
+{{! TODO: Following block is doesn't handle duplicated mapping of models. Not sure how to handle that yet. For example red_apple and green_apple both mapping to Apple model.}}
+{{^anyOf}}
+ {{^oneOf}}
+ {{#mappedModels}}
+ const factory {{classname}}.as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{modelName}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}({
+ required {{#lambda.titlecase}}{{#PrimitiveInUnion}}{{modelName}}{{/PrimitiveInUnion}}{{/lambda.titlecase}} {{#lambda.camelcase}}{{modelName}}Value{{/lambda.camelcase}}
+ }) = {{classname}}As{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{modelName}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}};
+ {{/mappedModels}}
+ {{/oneOf}}
+{{/anyOf}}
+const factory {{classname}}.unknown({
+ @Default('Json does not satisfy any available types') String message,
+ required Map json,
+
+ @Default(DeserializationErrorType.UnKnownType)
+ DeserializationErrorType errorType,
+
+ @Default([{{#anyOf}}{{{.}}},{{/anyOf}}{{#oneOf}}{{{.}}},{{/oneOf}}])
+ List possibleTypes,
+
+ @Default(<{{classname}}>[])
+ List<{{classname}}> deserializedModels,
+}) = {{classname}}Unknown;
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/parse_json_iteratively.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/parse_json_iteratively.mustache
new file mode 100644
index 000000000000..0cab7b060962
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/parse_json_iteratively.mustache
@@ -0,0 +1,41 @@
+final fromJsonMethods = >[{{#anyOf}}{{#lambda.titlecase}}{{#PrimitiveFromJson}}{{{.}}}{{/PrimitiveFromJson}}{{/lambda.titlecase}}.fromJson,{{/anyOf}}{{#oneOf}}{{#lambda.titlecase}}{{#PrimitiveFromJson}}{{{.}}}{{/PrimitiveFromJson}}{{/lambda.titlecase}}.fromJson,{{/oneOf}}];
+final deserializedModels = <{{classname}}>[];
+for (final fromJsonMethod in fromJsonMethods) {
+ try {
+ final dynamic parsedModel= fromJsonMethod.call(json);
+ // Note following line won't be executed if already the above parsing fails.
+ {{#anyOf}}
+ if (parsedModel is {{#lambda.titlecase}}{{#PrimitiveInUnion}}{{{.}}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}) {
+ deserializedModel = {{classname}}.as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}(
+ {{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}Value : parsedModel,
+ );
+ } else
+ {{/anyOf}}
+ {{#oneOf}}
+ if (parsedModel is {{#lambda.titlecase}}{{#PrimitiveInUnion}}{{{.}}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}) {
+ deserializedModel = {{classname}}.as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}(
+ {{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}Value : parsedModel,
+ );
+ } else
+ {{/oneOf}}
+ {
+ deserializedModel = {{classname}}.unknown(json: json);
+ }
+ deserializedModels.add(deserializedModel);
+ } catch (e) {
+ // We are suppressing the deserialization error when the json could not
+ // be parsed into one of the model. Because we return [{{classname}}.unknown]
+ // if the deserialization fails.
+ }
+}
+// Return an unknown type when the incoming json parses into more than one models.
+// Since we pass deserializedModels, clients can still use the deserialized model.
+// EvenThough this is valid for AnyOf types, Dart doesn't have polymorphic types.
+// So we still return this as an unknown type.
+if(deserializedModels.length > 1){
+ deserializedModel = {{classname}}.unknown(
+ json: json,
+ deserializedModels: deserializedModels,
+ errorType: DeserializationErrorType.MoreThanOneTypeSatisfied,
+ );
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/to_json_oneof_anyof.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/to_json_oneof_anyof.mustache
new file mode 100644
index 000000000000..d12c9e1b3365
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/additional_templates/to_json_oneof_anyof.mustache
@@ -0,0 +1,21 @@
+Map toJson() {
+ return when(
+ {{#anyOf}}
+ as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}: (as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}) => as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}.toJson(),
+ {{/anyOf}}
+ {{#oneOf}}
+ as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}: (as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}) => as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{{.}}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}.toJson(),
+ {{/oneOf}}
+ {{! Sometimes discrintors are mentioned in parent classes}}
+ {{! TODO: Following block is doesn't handle duplicated mapping of models. Not sure how to handle that yet. For example red_apple and green_apple both mapping to Apple model.}}
+ {{^anyOf}}
+ {{^oneOf}}
+ {{#mappedModels}}
+ as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{modelName}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}: (as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{modelName}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}) => as{{#lambda.titlecase}}{{#PrimitiveInUnion}}{{#lambda.camelcase}}{{modelName}}{{/lambda.camelcase}}{{/PrimitiveInUnion}}{{/lambda.titlecase}}.toJson(),
+ {{/mappedModels}}
+ {{/oneOf}}
+ {{/anyOf}}
+ {{! adds an unknown case to handle one Of}}
+ unknown: (message, json, errorType, possibleTypes, deserializedModels) => {},
+ );
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/constructor.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/constructor.mustache
new file mode 100644
index 000000000000..a772c3148eaa
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/constructor.mustache
@@ -0,0 +1 @@
+ const {{classname}}(this._dio);
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/deserialize.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/deserialize.mustache
new file mode 100644
index 000000000000..4dae0a6476f4
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/deserialize.mustache
@@ -0,0 +1,38 @@
+{{#freezedUnionResponse}}
+ _responseData = {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Data.toUnionData(_response.statusCode, _response.data,);
+{{/freezedUnionResponse}}
+{{^freezedUnionResponse}}
+ {{#isResponseFile}}
+ _responseData = _response.data as {{{returnType}}};
+ {{/isResponseFile}}
+ {{^isResponseFile}}
+ {{#returnSimpleType}}
+ {{#returnTypeIsPrimitive}}
+ _responseData = _response.data as {{{returnType}}};
+ {{/returnTypeIsPrimitive}}
+ {{^returnTypeIsPrimitive}}
+ _responseData = {{{returnType}}}.fromJson(_response.data as Map);
+ {{/returnTypeIsPrimitive}}
+ {{/returnSimpleType}}
+ {{^returnSimpleType}}
+ {{#returnTypeIsPrimitive}}
+ _responseData = _response.data as {{{returnType}}};
+ {{/returnTypeIsPrimitive}}
+ {{^returnTypeIsPrimitive}}
+ {{#isArray}}
+ {{#uniqueItems}}
+ final _responseDataAsSet = _response.data as List;
+ _responseData = _responseDataAsSet.map<{{{returnBaseType}}}>((dynamic e)=> {{{returnBaseType}}}.fromJson(e as Map)).toSet();
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ final _responseDataAsList = _response.data as List;
+ _responseData = _responseDataAsList.map<{{{returnBaseType}}}>((dynamic e)=> {{{returnBaseType}}}.fromJson(e as Map)).toList();
+ {{/uniqueItems}}
+ {{/isArray}}
+ {{#isMap}}
+ _responseData = _response.data as Map;
+ {{/isMap}}
+ {{/returnTypeIsPrimitive}}
+ {{/returnSimpleType}}
+ {{/isResponseFile}}
+{{/freezedUnionResponse}}
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/deserialize_union.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/deserialize_union.mustache
new file mode 100644
index 000000000000..b04cd2195339
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/deserialize_union.mustache
@@ -0,0 +1,53 @@
+{{#isFile}}
+ _responseData = responseData as {{{dataType}}};
+{{/isFile}}
+{{^isFile}}
+ {{#simpleType}}
+ {{#primitiveType}}
+ {{#dataType}}
+ _responseData = responseData as {{{dataType}}};
+ {{/dataType}}
+ {{^dataType}}
+ _responseData = responseData;
+ {{/dataType}}
+ {{/primitiveType}}
+ {{^primitiveType}}
+ {{#dataType}}
+ _responseData = {{{dataType}}}.fromJson(responseData as Map);
+ {{/dataType}}
+ {{^dataType}}
+ _responseData = responseData;
+ {{/dataType}}
+ {{/primitiveType}}
+ {{/simpleType}}
+ {{^simpleType}}
+ {{#primitiveType}}
+ _responseData = responseData as {{{dataType}}};
+ {{/primitiveType}}
+ {{^primitiveType}}
+ {{#isModel}}
+ {{#isMap}}
+ _responseData = responseData as {{{dataType}}};
+ {{/isMap}}
+ {{^isMap}}
+ _responseData = {{{dataType}}}.fromJson(responseData as Map);
+ {{/isMap}}
+ {{/isModel}}
+ {{^isModel}}
+ {{#isArray}}
+ {{#uniqueItems}}
+ final _responseDataAsSet = responseData as List;
+ _responseData = _responseDataAsSet.map<{{{baseType}}}>((dynamic e)=> {{{baseType}}}.fromJson(e as Map)).toSet();
+ {{/uniqueItems}}
+ {{^uniqueItems}}
+ final _responseDataAsList = responseData as List;
+ _responseData = _responseDataAsList.map<{{{baseType}}}>((dynamic e)=> {{{baseType}}}.fromJson(e as Map)).toList();
+ {{/uniqueItems}}
+ {{/isArray}}
+ {{#isMap}}
+ _responseData = responseData as Map;
+ {{/isMap}}
+ {{/isModel}}
+ {{/primitiveType}}
+ {{/simpleType}}
+{{/isFile}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/imports.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/imports.mustache
new file mode 100644
index 000000000000..ac933ec55504
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/imports.mustache
@@ -0,0 +1,2 @@
+import 'dart:convert';
+import '../model/models.dart';
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/query_param.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/query_param.mustache
new file mode 100644
index 000000000000..7e5f88400403
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/query_param.mustache
@@ -0,0 +1 @@
+{{{paramName}}}{{#isEnumRef}}.value{{/isEnumRef}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/serialize.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/serialize.mustache
new file mode 100644
index 000000000000..359a9a5697fc
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/api/serialize.mustache
@@ -0,0 +1,28 @@
+{{#hasFormParams}}
+ {{#isMultipart}}
+ _bodyData = FormData.fromMap({
+ {{#formParams}}
+ {{^required}}
+ {{^isNullable}}if ({{{paramName}}} != null) {{/isNullable}}
+ {{/required}}r'{{{baseName}}}':
+ {{#isFile}}{{{paramName}}}{{#isArray}}.toList(){{/isArray}}{{/isFile}}
+ {{^isFile}}jsonEncode({{{paramName}}}){{/isFile}},
+ {{/formParams}}
+ });
+ {{/isMultipart}}
+ {{^isMultipart}}
+ _bodyData = {
+ {{#formParams}}
+ {{^required}}{{^isNullable}}if ({{{paramName}}} != null) {{/isNullable}}{{/required}}r'{{{baseName}}}': {{>serialization/freezed/api/query_param}},
+ {{/formParams}}
+ };
+ {{/isMultipart}}
+{{/hasFormParams}}
+{{#bodyParam}}
+ {{#isPrimitiveType}}
+ _bodyData = {{paramName}}{{#isFile}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}.finalize(){{/isFile}};
+ {{/isPrimitiveType}}
+ {{^isPrimitiveType}}
+ _bodyData=jsonEncode({{{paramName}}});
+ {{/isPrimitiveType}}
+{{/bodyParam}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/build.yaml.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/build.yaml.mustache
new file mode 100644
index 000000000000..dee5edd67f90
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/build.yaml.mustache
@@ -0,0 +1,11 @@
+targets:
+ $default:
+ builders:
+ freezed|freezed:
+ # This restricts freezed build runner to look
+ # files only inside models folder.
+ # If you prefer the build runner to scan the whole
+ # project for files then simply remove this build.yaml file
+ generate_for:
+ include:
+ - "lib/src/model/**.dart"
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class.mustache
new file mode 100644
index 000000000000..b3b1ebfa08d6
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class.mustache
@@ -0,0 +1,46 @@
+part of 'models.dart';
+
+/// {{{description}}}{{^description}}{{classname}}{{/description}}
+{{#hasVars}}
+ ///
+ /// Properties:
+ {{#allVars}}
+ /// * [{{{name}}}] {{#description}}- {{{.}}}{{/description}}
+ {{/allVars}}
+{{/hasVars}}
+
+{{>serialization/freezed/class_factory}}
+
+{{>serialization/freezed/class_from_json}}
+
+{{>serialization/freezed/class_to_json}}
+
+
+}
+
+{{!
+extension for collection primitives in union
+}}
+{{>serialization/freezed/class_primitive_union_extensions}}
+
+{{!
+ Generate an enum for any variables that are declared as inline enums
+ isEnum is only true for inline variables that are enums.
+ If an enum is declared as a definition, isEnum is false and the enum is generated from the
+ enum.mustache template.
+}}
+{{#vars}}
+ {{^isModel}}
+ {{#enumName}}
+ {{^isContainer}}
+ {{>serialization/freezed/enum_inline}}
+ {{/isContainer}}
+ {{#isContainer}}
+ {{#mostInnerItems}}
+
+ {{>serialization/freezed/enum_inline}}
+ {{/mostInnerItems}}
+ {{/isContainer}}
+ {{/enumName}}
+ {{/isModel}}
+{{/vars}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_factory.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_factory.mustache
new file mode 100644
index 000000000000..9a2647243094
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_factory.mustache
@@ -0,0 +1,43 @@
+{{#vendorExtensions.x-is-pure}}
+ {{^hasDiscriminatorWithNonEmptyMapping}}
+ {{>serialization/freezed/class_factory_general}}
+ {{/hasDiscriminatorWithNonEmptyMapping}}
+ {{#hasDiscriminatorWithNonEmptyMapping}}
+ {{#discriminator}}
+ {{>serialization/freezed/additional_templates/freezed_union_for_oneof_anyof}}
+ {{/discriminator}}
+ {{^discriminator}}
+ {{#vendorExtensions.x-parent-discriminator}}
+ {{>serialization/freezed/additional_templates/freezed_union_for_oneof_anyof}}
+ {{/vendorExtensions.x-parent-discriminator}}
+ {{/discriminator}}
+ {{/hasDiscriminatorWithNonEmptyMapping}}
+{{/vendorExtensions.x-is-pure}}
+
+{{^vendorExtensions.x-is-pure}}
+ {{#vendorExtensions.x-is-child}}
+ {{^hasDiscriminatorWithNonEmptyMapping}}
+ {{>serialization/freezed/class_factory_general}}
+ {{/hasDiscriminatorWithNonEmptyMapping}}
+ {{/vendorExtensions.x-is-child}}
+{{/vendorExtensions.x-is-pure}}
+
+{{^vendorExtensions.x-is-pure}}
+ {{#hasDiscriminatorWithNonEmptyMapping}}
+ {{#discriminator}}
+ {{>serialization/freezed/additional_templates/freezed_union_for_oneof_anyof}}
+ {{/discriminator}}
+ {{^discriminator}}
+ {{#vendorExtensions.x-parent-discriminator}}
+ {{>serialization/freezed/additional_templates/freezed_union_for_oneof_anyof}}
+ {{/vendorExtensions.x-parent-discriminator}}
+ {{/discriminator}}
+ {{/hasDiscriminatorWithNonEmptyMapping}}
+{{/vendorExtensions.x-is-pure}}
+{{^vendorExtensions.x-is-pure}}
+ {{^vendorExtensions.x-is-child}}
+ {{^hasDiscriminatorWithNonEmptyMapping}}
+ {{>serialization/freezed/additional_templates/freezed_union_for_oneof_anyof}}
+ {{/hasDiscriminatorWithNonEmptyMapping}}
+ {{/vendorExtensions.x-is-child}}
+{{/vendorExtensions.x-is-pure}}
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_factory_general.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_factory_general.mustache
new file mode 100644
index 000000000000..a625abfc8202
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_factory_general.mustache
@@ -0,0 +1,12 @@
+@freezed
+class {{classname}} with _${{classname}} {
+const {{classname}}._();
+
+const factory {{classname}}({
+{{#vars}}
+ {{#description}}
+ /// {{{.}}}
+ {{/description}}
+ @JsonKey(name: r'{{baseName}}') {{>serialization/freezed/variable_type}} {{name}},
+{{/vars}}
+}) = _{{classname}};
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_from_json.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_from_json.mustache
new file mode 100644
index 000000000000..f9c12c8f8997
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_from_json.mustache
@@ -0,0 +1,116 @@
+{{#vendorExtensions.x-is-pure}}
+ {{^hasDiscriminatorWithNonEmptyMapping}}
+ factory {{classname}}.fromJson(Map json) => _${{classname}}FromJson(json);
+ {{/hasDiscriminatorWithNonEmptyMapping}}
+ {{#hasDiscriminatorWithNonEmptyMapping}}
+ factory {{classname}}.fromJson(Map json) {
+ {{#discriminator}}
+ switch(json['{{propertyBaseName}}']){
+ {{>serialization/freezed/additional_templates/case_parse_json_using_discriminator_mapping_value}}
+ }
+ return {{classname}}.unknown(json: json);
+ {{/discriminator}}
+ {{^discriminator}}
+ {{#vendorExtensions.x-parent-discriminator}}
+ // So we try to parse the json based on the discriminator value and try to
+ // return one of the valid model. Note: this approach tries
+ // to return one valid model and if more than one model
+ // is valid it then returns unknown type along with the json so the
+ // consumer can decide which model it is.
+ switch(json['{{propertyBaseName}}']){
+ {{>serialization/freezed/additional_templates/case_parse_json_using_discriminator_mapping_value}}
+ default:
+ /// If deserializedModel is still null, then we try to parse
+ /// the json against all the models and try to return one of the valid model.
+ /// Note: this approach tries to return one valid model and if more than one model
+ /// is valid it then returns unknown type along with the json so
+ /// the consumer can decide which model it is.
+ {{classname}}? deserializedModel;
+ {{>serialization/freezed/additional_templates/parse_json_iteratively}}
+ return deserializedModel ?? {{classname}}.unknown(json: json);
+ }
+ {{/vendorExtensions.x-parent-discriminator}}
+ {{/discriminator}}
+ }
+ {{/hasDiscriminatorWithNonEmptyMapping}}
+{{/vendorExtensions.x-is-pure}}
+{{^vendorExtensions.x-is-pure}}
+ {{#vendorExtensions.x-is-child}}
+ {{^hasDiscriminatorWithNonEmptyMapping}}
+ factory {{classname}}.fromJson(Map json) => _${{classname}}FromJson(json);
+ {{/hasDiscriminatorWithNonEmptyMapping}}
+ {{/vendorExtensions.x-is-child}}
+{{/vendorExtensions.x-is-pure}}
+
+{{^vendorExtensions.x-is-pure}}
+ {{#hasDiscriminatorWithNonEmptyMapping}}
+ factory {{classname}}.fromJson(Map json) {
+ {{#discriminator}}
+ switch(json['{{propertyBaseName}}']){
+ {{>serialization/freezed/additional_templates/case_parse_json_using_discriminator_mapping_value}}
+ }
+ return {{classname}}.unknown(json: json);
+ {{/discriminator}}
+ {{^discriminator}}
+ {{#vendorExtensions.x-parent-discriminator}}
+ // So we try to parse the json based on the discriminator value and try to
+ // return one of the valid model. Note: this approach tries
+ // to return one valid model and if more than one model
+ // is valid it then returns unknown type along with the json so the
+ // consumer can decide which model it is.
+ switch(json['{{propertyBaseName}}']){
+ {{>serialization/freezed/additional_templates/case_parse_json_using_discriminator_mapping_value}}
+ default:
+ /// If deserializedModel is still null, then we try to parse
+ /// the json against all the models and try to return one of the valid model.
+ /// Note: this approach tries to return one valid model and if more than one model
+ /// is valid it then returns unknown type along with the json so
+ /// the consumer can decide which model it is.
+ {{classname}}? deserializedModel;
+ {{>serialization/freezed/additional_templates/parse_json_iteratively}}
+ return deserializedModel ?? {{classname}}.unknown(json: json);
+ }
+ {{/vendorExtensions.x-parent-discriminator}}
+ {{/discriminator}}
+ }
+ {{/hasDiscriminatorWithNonEmptyMapping}}
+{{/vendorExtensions.x-is-pure}}
+
+{{^vendorExtensions.x-is-pure}}
+ {{^vendorExtensions.x-is-child}}
+ {{^hasDiscriminatorWithNonEmptyMapping}}
+ factory {{classname}}.fromJson(Map json) {
+ {{#discriminator}}
+ {{classname}}? deserializedModel;
+ // A discriminator property is specified but no mapping
+ // is provided in the spec, so we expect the property to
+ // have the value of the name of the model. Model prefix &
+ // suffix are ignored, as this is not known by the api provider
+ switch(json['{{propertyBaseName}}']){
+ {{>serialization/freezed/additional_templates/case_parse_json_using_model_name}}
+ default:
+ /// If deserializedModel is still null, then we try to parse
+ /// the json against all the models and try to return one of the valid model.
+ /// Note: this approach tries to return one valid model and if more than one model
+ /// is valid it then returns unknown type along with the json so
+ /// the consumer can decide which model it is.
+ {{>serialization/freezed/additional_templates/parse_json_iteratively}}
+ break;
+ }
+ return deserializedModel ?? {{classname}}.unknown(json: json);
+ {{/discriminator}}
+ {{^discriminator}}
+ // A discriminator property is not defined in the spec so
+ // we try to parse the json against all the models and try to
+ // return one of the valid model. Note: this approach tries
+ // to return one valid model and if more than one model
+ // is valid it then returns unknown type along with the json so
+ // the consumer can decide which model it is.
+ {{classname}}? deserializedModel;
+ {{>serialization/freezed/additional_templates/parse_json_iteratively}}
+ return deserializedModel ?? {{classname}}.unknown(json: json);
+ {{/discriminator}}
+ }
+ {{/hasDiscriminatorWithNonEmptyMapping}}
+ {{/vendorExtensions.x-is-child}}
+{{/vendorExtensions.x-is-pure}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_primitive_union_extensions.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_primitive_union_extensions.mustache
new file mode 100644
index 000000000000..a05e6c0727c6
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_primitive_union_extensions.mustache
@@ -0,0 +1,16 @@
+{{^vendorExtensions.x-is-pure}}
+ {{^vendorExtensions.x-is-child}}
+ {{^hasDiscriminatorWithNonEmptyMapping}}
+ {{#anyOf}}
+ {{#PrimitiveCollectionsExtension}}
+ {{{.}}}
+ {{/PrimitiveCollectionsExtension}}
+ {{/anyOf}}
+ {{#oneOf}}
+ {{#PrimitiveCollectionsExtension}}
+ {{{.}}}
+ {{/PrimitiveCollectionsExtension}}
+ {{/oneOf}}
+ {{/hasDiscriminatorWithNonEmptyMapping}}
+ {{/vendorExtensions.x-is-child}}
+{{/vendorExtensions.x-is-pure}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_to_json.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_to_json.mustache
new file mode 100644
index 000000000000..31cdf88a01a5
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/class_to_json.mustache
@@ -0,0 +1,18 @@
+{{#hasDiscriminatorWithNonEmptyMapping}}
+ {{#discriminator}}
+ {{>serialization/freezed/additional_templates/to_json_oneof_anyof}}
+ {{/discriminator}}
+ {{^discriminator}}
+ {{#vendorExtensions.x-parent-discriminator}}
+ {{>serialization/freezed/additional_templates/to_json_oneof_anyof}}
+ {{/vendorExtensions.x-parent-discriminator}}
+ {{/discriminator}}
+{{/hasDiscriminatorWithNonEmptyMapping}}
+
+{{^vendorExtensions.x-is-pure}}
+ {{^vendorExtensions.x-is-child}}
+ {{^hasDiscriminatorWithNonEmptyMapping}}
+ {{>serialization/freezed/additional_templates/to_json_oneof_anyof}}
+ {{/hasDiscriminatorWithNonEmptyMapping}}
+ {{/vendorExtensions.x-is-child}}
+{{/vendorExtensions.x-is-pure}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/enum.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/enum.mustache
new file mode 100644
index 000000000000..e5711b6f25cf
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/enum.mustache
@@ -0,0 +1,13 @@
+part of 'models.dart';
+
+{{#description}}/// {{{description}}}{{/description}}
+@JsonEnum(valueField: 'value')
+enum {{classname}} {
+ {{#allowableValues}}
+ {{#enumVars}}
+ {{{name}}}(value: {{#isString}}r{{/isString}}{{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
+ {{/enumVars}}
+ const {{classname}}({required this.value});
+ final {{dataType}} value;
+ {{/allowableValues}}
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/enum_inline.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/enum_inline.mustache
new file mode 100644
index 000000000000..3c94941bfd9c
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/enum_inline.mustache
@@ -0,0 +1,14 @@
+{{#description}}/// {{{description}}}{{/description}}
+{{#isDeprecated}}
+ @Deprecated('{{{enumName}}} has been deprecated')
+{{/isDeprecated}}
+@JsonEnum(valueField: 'value')
+enum {{enumName}} {
+ {{#allowableValues}}
+ {{#enumVars}}
+ {{{name}}}(value: {{#isString}}r{{/isString}}{{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
+ {{/enumVars}}
+ const {{enumName}}({required this.value});
+ final {{baseType}} value;
+ {{/allowableValues}}
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/models.dart.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/models.dart.mustache
new file mode 100644
index 000000000000..ff65bbd9cec3
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/models.dart.mustache
@@ -0,0 +1,24 @@
+//ignore_for_file: invalid_annotation_target
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'package:dio/dio.dart';
+import 'dart:convert';
+
+part 'models.freezed.dart';
+part 'models.g.dart';
+
+part 'primitive_union_types.dart';
+{{#freezedUnionResponse}}
+part 'response_models.dart';
+{{/freezedUnionResponse}}
+{{! Add part deifinition for all models}}
+{{#models}}{{#model}}part '{{classFilename}}.dart';{{/model}}{{/models}}
+
+/// A typedef used in the deserialization of OneOf and AnyOf
+/// models when no discriminator mapping is provided.
+typedef FromJsonMethodType = T Function(Map);
+
+/// Deserialization error types for OneOf and AnyOf types.
+enum DeserializationErrorType {
+ MoreThanOneTypeSatisfied,
+ UnKnownType,
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/primitive_union_types.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/primitive_union_types.mustache
new file mode 100644
index 000000000000..fafa083471b8
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/primitive_union_types.mustache
@@ -0,0 +1,60 @@
+part of 'models.dart';
+
+@freezed
+class IntInUnion with _$IntInUnion{
+ const factory IntInUnion({
+ required int intValue
+ }) = _IntInUnion;
+
+ factory IntInUnion.fromJson(Map json) => _$IntInUnionFromJson(json);
+}
+
+@freezed
+class StringInUnion with _$StringInUnion{
+ const factory StringInUnion({
+ required String stringValue
+ }) = _StringInUnion;
+
+ factory StringInUnion.fromJson(Map json) => _$StringInUnionFromJson(json);
+}
+@freezed
+class BoolInUnion with _$BoolInUnion{
+ const factory BoolInUnion({
+ required bool boolValue
+ }) = _BoolInUnion;
+
+ factory BoolInUnion.fromJson(Map json) => _$BoolInUnionFromJson(json);
+}
+
+@freezed
+class DoubleInUnion with _$DoubleInUnion{
+ const factory DoubleInUnion({
+ required double doubleValue
+ }) = _DoubleInUnion;
+
+ factory DoubleInUnion.fromJson(Map json) => _$DoubleInUnionFromJson(json);
+}
+
+@freezed
+class ObjectInUnion with _$ObjectInUnion {
+ const factory ObjectInUnion({required Object objectValue}) = _ObjectInUnion;
+
+ factory ObjectInUnion.fromJson(Map json) =>
+ _$ObjectInUnionFromJson(json);
+}
+
+@freezed
+class NumInUnion with _$NumInUnion{
+ const factory NumInUnion({required num numValue}) = _NumInUnion;
+
+ factory NumInUnion.fromJson(Map json) => _$NumInUnionFromJson(json);
+}
+
+@freezed
+class DateTimeInUnion with _$DateTimeInUnion {
+const factory DateTimeInUnion({required DateTime dateTimeValue}) =
+_DateTimeInUnion;
+
+factory DateTimeInUnion.fromJson(Map json) =>
+_$DateTimeInUnionFromJson(json);
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/response_models.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/response_models.mustache
new file mode 100644
index 000000000000..82852bdf7249
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/response_models.mustache
@@ -0,0 +1,40 @@
+part of 'models.dart';
+
+{{#apiInfo}}{{#apis}}
+{{#operations}}
+ {{#operation}}
+ @freezed
+ sealed class {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Data with _${{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Data {
+ const {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Data._();
+ {{#responses}}
+ const factory {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Data.as{{code}}{{^returnType}}Void{{/returnType}}({
+ required {{{dataType}}}{{^dataType}}Object?{{/dataType}} responseData,
+ }) = {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}DataAs{{code}}{{^returnType}}Void{{/returnType}};
+ {{/responses}}
+ const factory {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Data.unknown({
+ int? statusCode,
+ required Object? responseData,
+ }) = {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}ResponseUnknown;
+
+ /// Converts the incoming response into the correct response code based freezed union case.
+ static {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Data toUnionData(int? statusCode, Object? responseData) {
+
+ switch (statusCode) {
+ {{#responses}}
+ case {{code}}:
+ {{{dataType}}}{{^dataType}}Object?{{/dataType}} _responseData;
+ {{>serialization/freezed/api/deserialize_union}}
+ return {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Data.as{{code}}{{^returnType}}Void{{/returnType}}(
+ responseData: _responseData
+ );
+ {{/responses}}
+ default:
+ return {{#lambda.titlecase}}{{nickname}}{{/lambda.titlecase}}Data.unknown(
+ responseData: responseData,
+ );
+ }
+ }
+ }
+ {{/operation}}
+{{/operations}}
+{{/apis}}{{/apiInfo}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/test_instance.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/test_instance.mustache
new file mode 100644
index 000000000000..1b32f6768164
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/test_instance.mustache
@@ -0,0 +1,2 @@
+ final {{{classname}}}? instance = /* {{{classname}}}(...) */ null;
+ // TODO add properties to the entity
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/variable_type.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/variable_type.mustache
new file mode 100644
index 000000000000..e70ac3cdb41a
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/freezed/variable_type.mustache
@@ -0,0 +1,14 @@
+{{!
+Required Nullable Result
+true true required Type?
+true false required Type
+false true Type?
+false false Type?
+}}
+
+{{#required}}
+ {{#required}}required {{/required}}{{#isContainer}}{{baseType}}<{{#isMap}}String, {{/isMap}}{{#items}}{{>serialization/freezed/variable_type}}{{/items}}>{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}{{/isContainer}}{{#isNullable}}?{{/isNullable}}
+{{/required}}
+{{^required}}
+ {{#isContainer}}{{baseType}}<{{#isMap}}String, {{/isMap}}{{#items}}{{>serialization/freezed/variable_type}}{{/items}}>{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}{{/isContainer}}?
+{{/required}}
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/.gitignore b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/.gitignore
new file mode 100644
index 000000000000..4298cdcbd1a2
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/.gitignore
@@ -0,0 +1,41 @@
+# See https://dart.dev/guides/libraries/private-files
+
+# Files and directories created by pub
+.dart_tool/
+.buildlog
+.packages
+.project
+.pub/
+build/
+**/packages/
+
+# Files created by dart2js
+# (Most Dart developers will use pub build to compile Dart, use/modify these
+# rules if you intend to use dart2js directly
+# Convention is to use extension '.dart.js' for Dart compiled to Javascript to
+# differentiate from explicit Javascript files)
+*.dart.js
+*.part.js
+*.js.deps
+*.js.map
+*.info.json
+
+# Directory created by dartdoc
+doc/api/
+
+# Don't commit pubspec lock file
+# (Library packages only! Remove pattern if developing an application package)
+pubspec.lock
+
+# Don’t commit files and directories created by other development environments.
+# For example, if your development environment creates any of the following files,
+# consider putting them in a global ignore file:
+
+# IntelliJ
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# Mac
+.DS_Store
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/.openapi-generator-ignore b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/.openapi-generator-ignore
new file mode 100644
index 000000000000..7484ee590a38
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/.openapi-generator-ignore
@@ -0,0 +1,23 @@
+# OpenAPI Generator Ignore
+# Generated by openapi-generator https://github.com/openapitools/openapi-generator
+
+# Use this file to prevent files from being overwritten by the generator.
+# The patterns follow closely to .gitignore or .dockerignore.
+
+# As an example, the C# client generator defines ApiClient.cs.
+# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
+#ApiClient.cs
+
+# You can match any string of characters against a directory, file or extension with a single asterisk (*):
+#foo/*/qux
+# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
+
+# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
+#foo/**/qux
+# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
+
+# You can also negate patterns with an exclamation (!).
+# For example, you can ignore all files in a docs folder with the file extension .md:
+#docs/*.md
+# Then explicitly reverse the ignore rule for a single file:
+#!docs/README.md
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/.openapi-generator/FILES b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/.openapi-generator/FILES
new file mode 100644
index 000000000000..2fc04eeca8a5
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/.openapi-generator/FILES
@@ -0,0 +1,25 @@
+.gitignore
+README.md
+analysis_options.yaml
+build.yaml
+doc/Apple.md
+doc/Banana.md
+doc/DefaultApi.md
+doc/Fruit.md
+doc/Orange.md
+lib/openapi.dart
+lib/src/api.dart
+lib/src/api/default_api.dart
+lib/src/auth/api_key_auth.dart
+lib/src/auth/auth.dart
+lib/src/auth/basic_auth.dart
+lib/src/auth/bearer_auth.dart
+lib/src/auth/oauth.dart
+lib/src/model/apple.dart
+lib/src/model/banana.dart
+lib/src/model/fruit.dart
+lib/src/model/models.dart
+lib/src/model/orange.dart
+lib/src/model/primitive_union_types.dart
+pubspec.yaml
+test/orange_test.dart
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/.openapi-generator/VERSION b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/.openapi-generator/VERSION
new file mode 100644
index 000000000000..9e0e9bce84b2
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/.openapi-generator/VERSION
@@ -0,0 +1 @@
+7.17.0-SNAPSHOT
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/README.md b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/README.md
new file mode 100644
index 000000000000..433ce79b90c3
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/README.md
@@ -0,0 +1,86 @@
+# openapi (EXPERIMENTAL)
+No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+
+This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
+
+- API version: 0.0.1
+- Generator version: 7.17.0-SNAPSHOT
+- Build package: org.openapitools.codegen.languages.DartDioClientCodegen
+
+## Requirements
+
+* Dart 2.15.0+ or Flutter 2.8.0+
+* Dio 5.0.0+ (https://pub.dev/packages/dio)
+
+## Installation & Usage
+
+### pub.dev
+To use the package from [pub.dev](https://pub.dev), please include the following in pubspec.yaml
+```yaml
+dependencies:
+ openapi: 1.0.0
+```
+
+### Github
+If this Dart package is published to Github, please include the following in pubspec.yaml
+```yaml
+dependencies:
+ openapi:
+ git:
+ url: https://github.com/GIT_USER_ID/GIT_REPO_ID.git
+ #ref: main
+```
+
+### Local development
+To use the package from your local drive, please include the following in pubspec.yaml
+```yaml
+dependencies:
+ openapi:
+ path: /path/to/openapi
+```
+
+## Getting Started
+
+Please follow the [installation procedure](#installation--usage) and then run the following:
+
+```dart
+import 'package:openapi/openapi.dart';
+
+
+final api = Openapi().getDefaultApi();
+
+try {
+ final response = await api.rootGet();
+ print(response);
+} catch on DioException (e) {
+ print("Exception when calling DefaultApi->rootGet: $e\n");
+}
+
+```
+
+## Documentation for API Endpoints
+
+All URIs are relative to *http://localhost*
+
+Class | Method | HTTP request | Description
+------------ | ------------- | ------------- | -------------
+[*DefaultApi*](doc/DefaultApi.md) | [**rootGet**](doc/DefaultApi.md#rootget) | **GET** / |
+
+
+## Documentation For Models
+
+ - [Apple](doc/Apple.md)
+ - [Banana](doc/Banana.md)
+ - [Fruit](doc/Fruit.md)
+ - [Orange](doc/Orange.md)
+
+
+## Documentation For Authorization
+
+Endpoints do not require authorization.
+
+
+## Author
+
+
+
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/analysis_options.yaml b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/analysis_options.yaml
new file mode 100644
index 000000000000..8ff047ce7675
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/analysis_options.yaml
@@ -0,0 +1,11 @@
+analyzer:
+ language:
+ strict-inference: true
+ strict-raw-types: true
+ strict-casts: false
+ exclude:
+ - test/*.dart
+ - lib/src/model/*.g.dart
+ - lib/src/model/*.freezed.dart
+ errors:
+ deprecated_member_use_from_same_package: ignore
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/build.yaml b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/build.yaml
new file mode 100644
index 000000000000..dee5edd67f90
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/build.yaml
@@ -0,0 +1,11 @@
+targets:
+ $default:
+ builders:
+ freezed|freezed:
+ # This restricts freezed build runner to look
+ # files only inside models folder.
+ # If you prefer the build runner to scan the whole
+ # project for files then simply remove this build.yaml file
+ generate_for:
+ include:
+ - "lib/src/model/**.dart"
\ No newline at end of file
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/Apple.md b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/Apple.md
new file mode 100644
index 000000000000..c7f711b87cef
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/Apple.md
@@ -0,0 +1,15 @@
+# openapi.model.Apple
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**kind** | **String** | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/Banana.md b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/Banana.md
new file mode 100644
index 000000000000..bef8a58a4276
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/Banana.md
@@ -0,0 +1,15 @@
+# openapi.model.Banana
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**count** | **num** | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/DefaultApi.md b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/DefaultApi.md
new file mode 100644
index 000000000000..b010661371f9
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/DefaultApi.md
@@ -0,0 +1,51 @@
+# openapi.api.DefaultApi
+
+## Load the API package
+```dart
+import 'package:openapi/api.dart';
+```
+
+All URIs are relative to *http://localhost*
+
+Method | HTTP request | Description
+------------- | ------------- | -------------
+[**rootGet**](DefaultApi.md#rootget) | **GET** / |
+
+
+# **rootGet**
+> Fruit rootGet()
+
+
+
+### Example
+```dart
+import 'package:openapi/api.dart';
+
+final api = Openapi().getDefaultApi();
+
+try {
+ final response = api.rootGet();
+ print(response);
+} catch on DioException (e) {
+ print('Exception when calling DefaultApi->rootGet: $e\n');
+}
+```
+
+### Parameters
+This endpoint does not need any parameter.
+
+### Return type
+
+[**Fruit**](Fruit.md)
+
+### Authorization
+
+No authorization required
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/Fruit.md b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/Fruit.md
new file mode 100644
index 000000000000..5239c1160576
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/Fruit.md
@@ -0,0 +1,18 @@
+# openapi.model.Fruit
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**color** | **String** | | [optional]
+**kind** | **String** | | [optional]
+**count** | **num** | | [optional]
+**sweet** | **bool** | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/Orange.md b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/Orange.md
new file mode 100644
index 000000000000..a07836f00534
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/doc/Orange.md
@@ -0,0 +1,15 @@
+# openapi.model.Orange
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**sweet** | **bool** | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/lib/openapi.dart b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/lib/openapi.dart
new file mode 100644
index 000000000000..581830866afb
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/lib/openapi.dart
@@ -0,0 +1,15 @@
+//
+// AUTO-GENERATED FILE, DO NOT MODIFY!
+//
+
+export 'package:openapi/src/api.dart';
+export 'package:openapi/src/auth/api_key_auth.dart';
+export 'package:openapi/src/auth/basic_auth.dart';
+export 'package:openapi/src/auth/bearer_auth.dart';
+export 'package:openapi/src/auth/oauth.dart';
+
+
+export 'package:openapi/src/api/default_api.dart';
+
+
+export 'package:openapi/src/model/models.dart';
\ No newline at end of file
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/lib/src/api.dart b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/lib/src/api.dart
new file mode 100644
index 000000000000..8943da413f65
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/lib/src/api.dart
@@ -0,0 +1,68 @@
+//
+// AUTO-GENERATED FILE, DO NOT MODIFY!
+//
+
+import 'package:dio/dio.dart';
+import 'package:openapi/src/auth/api_key_auth.dart';
+import 'package:openapi/src/auth/basic_auth.dart';
+import 'package:openapi/src/auth/bearer_auth.dart';
+import 'package:openapi/src/auth/oauth.dart';
+import 'package:openapi/src/api/default_api.dart';
+
+class Openapi {
+ static const String basePath = r'http://localhost';
+
+ final Dio dio;
+ Openapi({
+ Dio? dio,
+ String? basePathOverride,
+ List? interceptors,
+ }) :
+ this.dio = dio ??
+ Dio(BaseOptions(
+ baseUrl: basePathOverride ?? basePath,
+ connectTimeout: const Duration(milliseconds: 5000),
+ receiveTimeout: const Duration(milliseconds: 3000),
+ )) {
+ if (interceptors == null) {
+ this.dio.interceptors.addAll([
+ OAuthInterceptor(),
+ BasicAuthInterceptor(),
+ BearerAuthInterceptor(),
+ ApiKeyAuthInterceptor(),
+ ]);
+ } else {
+ this.dio.interceptors.addAll(interceptors);
+ }
+ }
+
+ void setOAuthToken(String name, String token) {
+ if (this.dio.interceptors.any((i) => i is OAuthInterceptor)) {
+ (this.dio.interceptors.firstWhere((i) => i is OAuthInterceptor) as OAuthInterceptor).tokens[name] = token;
+ }
+ }
+
+ void setBearerAuth(String name, String token) {
+ if (this.dio.interceptors.any((i) => i is BearerAuthInterceptor)) {
+ (this.dio.interceptors.firstWhere((i) => i is BearerAuthInterceptor) as BearerAuthInterceptor).tokens[name] = token;
+ }
+ }
+
+ void setBasicAuth(String name, String username, String password) {
+ if (this.dio.interceptors.any((i) => i is BasicAuthInterceptor)) {
+ (this.dio.interceptors.firstWhere((i) => i is BasicAuthInterceptor) as BasicAuthInterceptor).authInfo[name] = BasicAuthInfo(username, password);
+ }
+ }
+
+ void setApiKey(String name, String apiKey) {
+ if (this.dio.interceptors.any((i) => i is ApiKeyAuthInterceptor)) {
+ (this.dio.interceptors.firstWhere((element) => element is ApiKeyAuthInterceptor) as ApiKeyAuthInterceptor).apiKeys[name] = apiKey;
+ }
+ }
+
+ /// Get DefaultApi instance, base route and serializer can be overridden by a given but be careful,
+ /// by doing that all interceptors will not be executed
+ DefaultApi getDefaultApi() {
+ return DefaultApi(dio);
+ }
+}
diff --git a/samples/openapi3/client/petstore/dart-dio/freezed/oneof/lib/src/api/default_api.dart b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/lib/src/api/default_api.dart
new file mode 100644
index 000000000000..f2a138a7077e
--- /dev/null
+++ b/samples/openapi3/client/petstore/dart-dio/freezed/oneof/lib/src/api/default_api.dart
@@ -0,0 +1,89 @@
+//
+// AUTO-GENERATED FILE, DO NOT MODIFY!
+//
+
+import 'dart:async';
+
+import 'dart:convert';
+import '../model/models.dart';
+import 'package:dio/dio.dart';
+
+
+class DefaultApi {
+
+ final Dio _dio;
+
+ const DefaultApi(this._dio);
+
+ /// rootGet
+ ///
+ ///
+ /// Parameters:
+ /// * [cancelToken] - A [CancelToken] that can be used to cancel the operation
+ /// * [headers] - Can be used to add additional headers to the request
+ /// * [extras] - Can be used to add flags to the request
+ /// * [validateStatus] - A [ValidateStatus] callback that can be used to determine request success based on the HTTP status of the response
+ /// * [onSendProgress] - A [ProgressCallback] that can be used to get the send progress
+ /// * [onReceiveProgress] - A [ProgressCallback] that can be used to get the receive progress
+ ///
+ /// Returns a [Future] containing a [Response] with a [Fruit] as data
+ /// Throws [DioException] if API call or serialization fails
+ Future> rootGet({
+
+ CancelToken? cancelToken,
+ Map? headers,
+ Map? extra,
+ ValidateStatus? validateStatus,
+ ProgressCallback? onSendProgress,
+ ProgressCallback? onReceiveProgress,
+ }) async {
+ final _path = r'/';
+ final _options = Options(
+ method: r'GET',
+ headers: {
+ ...?headers,
+ },
+ extra: {
+ 'secure':