diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java index 4d7eb4dbe7c1..4389714fa119 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java @@ -622,6 +622,7 @@ public ModelsMap postProcessModels(ModelsMap objs) { if (useOptional) { for (ModelMap modelMap : objs.getModels()) { CodegenModel model = modelMap.getModel(); + boolean hasOptionalProperties = false; boolean shouldUseOptional; @@ -636,9 +637,12 @@ public ModelsMap postProcessModels(ModelsMap objs) { for (CodegenProperty prop : model.vars) { if (!prop.required && !prop.dataType.startsWith("Optional<")) { wrapPropertyWithOptional(prop); + hasOptionalProperties = true; } } } + + model.vendorExtensions.put("x-has-optional-properties", hasOptionalProperties); } } @@ -653,6 +657,7 @@ private void wrapPropertyWithOptional(CodegenProperty property) { boolean hasNullableSuffix = property.dataType.endsWith("?"); String baseType = hasNullableSuffix ? property.dataType.substring(0, property.dataType.length() - 1) : property.dataType; + property.vendorExtensions.put("x-unwrapped-datatype-nullable", baseType + "?"); property.dataType = "Optional<" + baseType + "?" + ">"; if (property.datatypeWithEnum != null && !property.datatypeWithEnum.startsWith("Optional<")) { @@ -660,6 +665,8 @@ private void wrapPropertyWithOptional(CodegenProperty property) { baseType = hasNullableSuffix ? property.datatypeWithEnum.substring(0, property.datatypeWithEnum.length() - 1) : property.datatypeWithEnum; property.datatypeWithEnum = "Optional<" + baseType + "?" + ">"; } + + property.isNullable = false; } @Override 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 880bb6258354..581624c15a8b 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 @@ -4,6 +4,8 @@ export 'package:{{pubName}}/{{sourceFolder}}/auth/api_key_auth.dart'; export 'package:{{pubName}}/{{sourceFolder}}/auth/basic_auth.dart'; export 'package:{{pubName}}/{{sourceFolder}}/auth/bearer_auth.dart'; export 'package:{{pubName}}/{{sourceFolder}}/auth/oauth.dart'; +{{#useOptional}}export 'package:{{pubName}}/{{sourceFolder}}/optional.dart'; +{{/useOptional}} {{#useBuiltValue}}export 'package:{{pubName}}/{{sourceFolder}}/serializers.dart'; {{#useDateLibCore}}export 'package:{{pubName}}/{{sourceFolder}}/{{modelPackage}}/date.dart';{{/useDateLibCore}}{{/useBuiltValue}} diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/optional.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/optional.mustache index 9a2747da4e52..f4fa6f8f2586 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/optional.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/optional.mustache @@ -19,7 +19,7 @@ import 'package:json_annotation/json_annotation.dart'; /// // Field has value - sends {"field": "value"} /// final patch3 = Model(field: const Optional.present('value')); /// ``` -sealed class Optional { +abstract class Optional { const Optional(); /// Creates an Optional with an absent value (not set). @@ -48,7 +48,7 @@ sealed class Optional { } /// Represents an absent Optional value. -final class Absent extends Optional { +class Absent extends Optional { const Absent(); @override @@ -77,7 +77,7 @@ final class Absent extends Optional { } /// Represents a present Optional value. -final class Present extends Optional { +class Present extends Optional { const Present(this._value); final T _value; diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class.mustache index 7a9ee688596b..b7ce07ace304 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class.mustache @@ -2,6 +2,8 @@ import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart';{{#oneOf}}{{#-first}} import 'package:one_of/one_of.dart';{{/-first}}{{/oneOf}}{{#anyOf}}{{#-first}} import 'package:one_of/any_of.dart';{{/-first}}{{/anyOf}} +{{#vendorExtensions.x-has-optional-properties}}import 'package:{{pubName}}/{{sourceFolder}}/optional.dart'; +{{/vendorExtensions.x-has-optional-properties}} {{#imports}} {{/imports}} diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_members.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_members.mustache index 50b7f98ba60d..cfc50dd82b87 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_members.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_members.mustache @@ -7,7 +7,7 @@ @Deprecated('{{{name}}} has been deprecated') {{/deprecated}} @BuiltValueField(wireName: r'{{baseName}}') - {{>serialization/built_value/variable_type}}{{^isNullable}}{{^required}}?{{/required}}{{/isNullable}} get {{name}}; + {{>serialization/built_value/variable_type}}{{^vendorExtensions.x-is-optional}}{{^isNullable}}{{^required}}?{{/required}}{{/isNullable}}{{/vendorExtensions.x-is-optional}} get {{name}}; {{#allowableValues}} // {{#min}}range from {{{min}}} to {{{max}}}{{/min}}{{^min}}enum {{name}}Enum { {{#values}} {{{.}}}, {{/values}} };{{/min}} {{/allowableValues}} @@ -31,8 +31,9 @@ factory {{classname}}([void updates({{classname}}Builder b)]) = _${{classname}}; @BuiltValueHook(initializeBuilder: true) - static void _defaults({{{classname}}}Builder b) => b{{#vendorExtensions.x-parent-discriminator}}..{{propertyName}}=b.discriminatorValue{{/vendorExtensions.x-parent-discriminator}}{{#vendorExtensions.x-self-and-ancestor-only-props}}{{#defaultValue}} - ..{{{name}}} = {{#isEnum}}{{^isContainer}}{{#enumName}}{{enumName}}.valueOf({{{defaultValue}}}){{/enumName}}{{^enumName}}{{{defaultValue}}}{{/enumName}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{defaultValue}}}{{/isEnum}}{{/defaultValue}}{{/vendorExtensions.x-self-and-ancestor-only-props}}; + static void _defaults({{{classname}}}Builder b) => b{{#vendorExtensions.x-parent-discriminator}}..{{propertyName}}=b.discriminatorValue{{/vendorExtensions.x-parent-discriminator}}{{#vendorExtensions.x-self-and-ancestor-only-props}}{{#vendorExtensions.x-is-optional}} + ..{{{name}}} = Optional.absent(){{/vendorExtensions.x-is-optional}}{{^vendorExtensions.x-is-optional}}{{#defaultValue}} + ..{{{name}}} = {{#isEnum}}{{^isContainer}}{{#enumName}}{{enumName}}.valueOf({{{defaultValue}}}){{/enumName}}{{^enumName}}{{{defaultValue}}}{{/enumName}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{defaultValue}}}{{/isEnum}}{{/defaultValue}}{{/vendorExtensions.x-is-optional}}{{/vendorExtensions.x-self-and-ancestor-only-props}}; {{/vendorExtensions.x-is-parent}} @BuiltValueSerializer(custom: true) static Serializer<{{classname}}> get serializer => _${{classname}}Serializer(); \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_serializer.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_serializer.mustache index 4cd02f3506de..ef0a6301bfa3 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_serializer.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/class_serializer.mustache @@ -11,6 +11,21 @@ class _${{classname}}Serializer implements PrimitiveSerializer<{{classname}}> { FullType specifiedType = FullType.unspecified, }) sync* { {{#vendorExtensions.x-self-and-ancestor-only-props}} + {{#vendorExtensions.x-is-optional}} + if (object.{{{name}}}.isPresent) { + yield r'{{baseName}}'; + final optionalValue = object.{{{name}}}.value; + if (optionalValue == null) { + yield null; + } else { + yield serializers.serialize( + optionalValue, + specifiedType: const {{>serialization/built_value/variable_serializer_type}}, + ); + } + } + {{/vendorExtensions.x-is-optional}} + {{^vendorExtensions.x-is-optional}} {{#required}} {{! A required property need to always be part of the serialized output. @@ -32,6 +47,7 @@ class _${{classname}}Serializer implements PrimitiveSerializer<{{classname}}> { ); } {{/required}} + {{/vendorExtensions.x-is-optional}} {{/vendorExtensions.x-self-and-ancestor-only-props}} } diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/deserialize_properties.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/deserialize_properties.mustache index d64ec8086c34..b04145f5b5a8 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/deserialize_properties.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/deserialize_properties.mustache @@ -12,6 +12,14 @@ switch (key) { {{#vendorExtensions.x-self-and-ancestor-only-props}} case r'{{baseName}}': + {{#vendorExtensions.x-is-optional}} + final valueDes = serializers.deserialize( + value, + specifiedType: const {{>serialization/built_value/variable_serializer_type}}, + ) as {{{vendorExtensions.x-unwrapped-datatype-nullable}}}; + result.{{{name}}} = Optional.present(valueDes); + {{/vendorExtensions.x-is-optional}} + {{^vendorExtensions.x-is-optional}} final valueDes = serializers.deserialize( value, specifiedType: const {{>serialization/built_value/variable_serializer_type}}, @@ -46,6 +54,7 @@ {{/isModel}} {{/isEnum}} {{/isContainer}} + {{/vendorExtensions.x-is-optional}} break; {{/vendorExtensions.x-self-and-ancestor-only-props}} default: diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/variable_serializer_type.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/variable_serializer_type.mustache index c76dde39a9c9..8116fcb4ede8 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/variable_serializer_type.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/variable_serializer_type.mustache @@ -1 +1 @@ -FullType{{#isNullable}}.nullable{{/isNullable}}({{#isContainer}}{{baseType}}, [{{#isMap}}FullType(String), {{/isMap}}{{#items}}{{>serialization/built_value/variable_serializer_type}}{{/items}}]{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}{{/isContainer}}) \ No newline at end of file +{{#vendorExtensions.x-is-optional}}{{#isContainer}}FullType{{#isNullable}}.nullable{{/isNullable}}({{baseType}}, [{{#isMap}}FullType(String), {{/isMap}}{{#items}}{{>serialization/built_value/variable_serializer_type}}{{/items}}]){{/isContainer}}{{^isContainer}}FullType.nullable({{{vendorExtensions.x-unwrapped-datatype}}}){{/isContainer}}{{/vendorExtensions.x-is-optional}}{{^vendorExtensions.x-is-optional}}FullType{{#isNullable}}.nullable{{/isNullable}}({{#isContainer}}{{baseType}}, [{{#isMap}}FullType(String), {{/isMap}}{{#items}}{{>serialization/built_value/variable_serializer_type}}{{/items}}]{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}{{/isContainer}}){{/vendorExtensions.x-is-optional}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/variable_type.mustache b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/variable_type.mustache index 136545525cac..78ca08f2a1c6 100644 --- a/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/variable_type.mustache +++ b/modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/variable_type.mustache @@ -1 +1 @@ -{{#isContainer}}{{baseType}}<{{#isMap}}String, {{/isMap}}{{#items}}{{>serialization/built_value/variable_type}}{{/items}}>{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}{{/isContainer}}{{#isNullable}}?{{/isNullable}} \ No newline at end of file +{{#isContainer}}{{baseType}}<{{#isMap}}String, {{/isMap}}{{#items}}{{>serialization/built_value/variable_type}}{{/items}}>{{/isContainer}}{{^isContainer}}{{{datatypeWithEnum}}}{{/isContainer}}{{#isNullable}}{{^vendorExtensions.x-is-optional}}?{{/vendorExtensions.x-is-optional}}{{/isNullable}} \ No newline at end of file