-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Description
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator?
- Have you tested with the latest master to confirm the issue still exists?
- Have you searched for related issues/PRs?
- What's the actual output vs expected output?
- [Optional] Sponsorship to speed up the bug fix or feature request
Description
When generating Dart code with the dart-dio generator using built_value serialization, fields that are converted to enums (via enum OR const properties) and also have a default value produce invalid Dart code that fails to compile.
The generator:
- Correctly creates an
EnumClassfor fields withenumorconstproperties - Incorrectly assigns the default value as a string literal instead of the corresponding enum constant
This produces a compilation error:
Error: A value of type 'String' can't be assigned to a variable of type 'DataConvertorTypeEnum?'.
..type = 'converter';
^
Important findings:
- The bug occurs with both
enumandconstproperties (both trigger enum generation) - Even after removing
enumand keeping onlyconst, the generator still creates an EnumClass and still has the bug - This commonly occurs when using FastAPI/Pydantic with
Literaltypes that have default values
openapi-generator version
- openapi-generator-cli version: 7.x (please specify your exact version)
- Generator:
dart-dio - Serialization library:
built_value
OpenAPI declaration file content or url
Minimal reproduction spec - Case 1: Using enum + default
openapi: 3.1.0
info:
title: Minimal Reproduction
version: 1.0.0
paths: {}
components:
schemas:
DataConvertor:
type: object
required:
- method
properties:
method:
type: string
type:
type: string
enum:
- converter
default: converterMinimal reproduction spec - Case 2: Using const + default (same bug)
openapi: 3.1.0
info:
title: Minimal Reproduction
version: 1.0.0
paths: {}
components:
schemas:
DataConvertor:
type: object
required:
- method
properties:
method:
type: string
type:
type: string
const: converter
default: converterBoth cases produce the same invalid Dart code.
Generation Details
openapi-generator-cli generate \
-i openapi.yaml \
-g dart-dio \
-o ./generated_client \
--additional-properties=serializationLibrary=built_valueSteps to reproduce
-
Create an OpenAPI spec with a schema that has a field with either:
enum: [single_value]+default: single_value, ORconst: single_value+default: single_value
-
Generate Dart client using
dart-diogenerator withbuilt_valueserialization -
Try to compile the generated code with
dart compileorflutter build -
Observe compilation error in the
_defaultsmethod
Actual Output
class DataConvertorTypeEnum extends EnumClass {
@BuiltValueEnumConst(wireName: r'converter')
static const DataConvertorTypeEnum converter = _$dataConvertorTypeEnum_converter;
static Serializer<DataConvertorTypeEnum> get serializer => _$dataConvertorTypeEnumSerializer;
const DataConvertorTypeEnum._(String name): super(name);
static BuiltSet<DataConvertorTypeEnum> get values => _$dataConvertorTypeEnumValues;
static DataConvertorTypeEnum valueOf(String name) => _$dataConvertorTypeEnumValueOf(name);
}
abstract class DataConvertor implements Built<DataConvertor, DataConvertorBuilder> {
@BuiltValueField(wireName: r'type')
DataConvertorTypeEnum? get type;
// enum typeEnum { converter, };
@BuiltValueHook(initializeBuilder: true)
static void _defaults(DataConvertorBuilder b) => b
..type = 'converter'; // ❌ COMPILE ERROR: String cannot be assigned to DataConvertorTypeEnum?
}Expected Output
class DataConvertorTypeEnum extends EnumClass {
@BuiltValueEnumConst(wireName: r'converter')
static const DataConvertorTypeEnum converter = _$dataConvertorTypeEnum_converter;
// ...
}
abstract class DataConvertor implements Built<DataConvertor, DataConvertorBuilder> {
@BuiltValueField(wireName: r'type')
DataConvertorTypeEnum? get type;
@BuiltValueHook(initializeBuilder: true)
static void _defaults(DataConvertorBuilder b) => b
..type = DataConvertorTypeEnum.converter; // ✅ CORRECT: Uses enum constant
}Related issues/PRs
- Possibly related to discriminator/polymorphism handling
- May affect other Dart generators with built_value serialization
Suggest a fix
The issue is in the mustache template for built_value model generation. When processing default values, the template should check if the field type is an enum and use the enum constant instead of the string literal.
Location: modules/openapi-generator/src/main/resources/dart/libraries/dio/serialization/built_value/
Current behavior (pseudo-template):
{{#vars}}
{{#defaultValue}}
..{{name}} = '{{{defaultValue}}}';
{{/defaultValue}}
{{/vars}}Expected behavior:
{{#vars}}
{{#defaultValue}}
{{#isEnum}}
..{{name}} = {{enumName}}.{{defaultValue}};
{{/isEnum}}
{{^isEnum}}
..{{name}} = '{{{defaultValue}}}';
{{/isEnum}}
{{/defaultValue}}
{{/vars}}Workaround
Until this is fixed, modify your OpenAPI spec (or the source that generates it) to remove both enum/const AND default from single-value discriminator fields:
Instead of (Pydantic/FastAPI):
type: Literal["converter"] = "converter"Use:
type: str = "converter"This generates a plain String field with a string default, which compiles correctly:
@BuiltValueField(wireName: r'type')
String? get type;
static void _defaults(DataConvertorBuilder b) => b
..type = 'converter'; // ✅ Valid: String to String?Trade-off: You lose client-side type validation for these discriminator fields, but server-side validation still works.