New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use toJson()
instead of .name
if enums have toJson()
.
#596
Conversation
source_gen@1.4.0 requires Dart 3.0.
Thanks for the great work. |
@trevorwang @kzrnm This breaks things if you're using freezed to generate |
@knyghtryda Could you take a example? My code is working as expected. notice: freezed doesn't build enum_json.dart import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:retrofit/retrofit.dart';
part 'enum_json.freezed.dart';
part 'enum_json.g.dart';
enum ByName {
jp,
zh,
kr,
}
@JsonEnum(valueField: 'value')
enum ByValue {
plus(1),
minus(-1),
;
const ByValue(this.value);
final int value;
int toJson() => value;
}
@freezed
class HasEnum with _$HasEnum {
@JsonSerializable(fieldRename: FieldRename.snake, explicitToJson: true)
const factory HasEnum({
required ByName byName,
required ByValue byValue,
}) = _HasEnum;
factory HasEnum.fromJson(Map<String, dynamic> json) =>
_$HasEnumFromJson(json);
}
@RestApi()
abstract class TestQueryParamEnumToJson {
@GET('/test')
Future<void> getTest({
@Query('country') required ByName byName,
@Query('sign') required ByValue byValue,
});
@POST('/test')
Future<void> petTest(@Body() HasEnum params);
} enum_json.g.dart// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'enum_json.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$_HasEnum _$$_HasEnumFromJson(Map<String, dynamic> json) => _$_HasEnum(
byName: $enumDecode(_$ByNameEnumMap, json['by_name']),
byValue: $enumDecode(_$ByValueEnumMap, json['by_value']),
);
Map<String, dynamic> _$$_HasEnumToJson(_$_HasEnum instance) =>
<String, dynamic>{
'by_name': _$ByNameEnumMap[instance.byName]!,
'by_value': instance.byValue.toJson(),
};
const _$ByNameEnumMap = {
ByName.jp: 'jp',
ByName.zh: 'zh',
ByName.kr: 'kr',
};
const _$ByValueEnumMap = {
ByValue.plus: 1,
ByValue.minus: -1,
};
// **************************************************************************
// RetrofitGenerator
// **************************************************************************
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers
class _TestQueryParamEnumToJson implements TestQueryParamEnumToJson {
_TestQueryParamEnumToJson(
this._dio, {
this.baseUrl,
});
final Dio _dio;
String? baseUrl;
@override
Future<void> getTest({
required ByName byName,
required ByValue byValue,
}) async {
const _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{
r'country': byName.name,
r'sign': byValue.toJson(),
};
final _headers = <String, dynamic>{};
final Map<String, dynamic>? _data = null;
await _dio.fetch<void>(_setStreamType<void>(Options(
method: 'GET',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/test',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
))));
}
@override
Future<void> petTest(HasEnum params) async {
const _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = <String, dynamic>{};
_data.addAll(params.toJson());
await _dio.fetch<void>(_setStreamType<void>(Options(
method: 'POST',
headers: _headers,
extra: _extra,
)
.compose(
_dio.options,
'/test',
queryParameters: queryParameters,
data: _data,
)
.copyWith(
baseUrl: _combineBaseUrls(
_dio.options.baseUrl,
baseUrl,
))));
}
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
if (T != dynamic &&
!(requestOptions.responseType == ResponseType.bytes ||
requestOptions.responseType == ResponseType.stream)) {
if (T == String) {
requestOptions.responseType = ResponseType.plain;
} else {
requestOptions.responseType = ResponseType.json;
}
}
return requestOptions;
}
String _combineBaseUrls(
String dioBaseUrl,
String? baseUrl,
) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}
final url = Uri.parse(baseUrl);
if (url.isAbsolute) {
return url.toString();
}
return Uri.parse(dioBaseUrl).resolveUri(url).toString();
}
} enum_json.freezed.dart// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'enum_json.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
HasEnum _$HasEnumFromJson(Map<String, dynamic> json) {
return _HasEnum.fromJson(json);
}
/// @nodoc
mixin _$HasEnum {
ByName get byName => throw _privateConstructorUsedError;
ByValue get byValue => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$HasEnumCopyWith<HasEnum> get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $HasEnumCopyWith<$Res> {
factory $HasEnumCopyWith(HasEnum value, $Res Function(HasEnum) then) =
_$HasEnumCopyWithImpl<$Res, HasEnum>;
@useResult
$Res call({ByName byName, ByValue byValue});
}
/// @nodoc
class _$HasEnumCopyWithImpl<$Res, $Val extends HasEnum>
implements $HasEnumCopyWith<$Res> {
_$HasEnumCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? byName = null,
Object? byValue = null,
}) {
return _then(_value.copyWith(
byName: null == byName
? _value.byName
: byName // ignore: cast_nullable_to_non_nullable
as ByName,
byValue: null == byValue
? _value.byValue
: byValue // ignore: cast_nullable_to_non_nullable
as ByValue,
) as $Val);
}
}
/// @nodoc
abstract class _$$_HasEnumCopyWith<$Res> implements $HasEnumCopyWith<$Res> {
factory _$$_HasEnumCopyWith(
_$_HasEnum value, $Res Function(_$_HasEnum) then) =
__$$_HasEnumCopyWithImpl<$Res>;
@override
@useResult
$Res call({ByName byName, ByValue byValue});
}
/// @nodoc
class __$$_HasEnumCopyWithImpl<$Res>
extends _$HasEnumCopyWithImpl<$Res, _$_HasEnum>
implements _$$_HasEnumCopyWith<$Res> {
__$$_HasEnumCopyWithImpl(_$_HasEnum _value, $Res Function(_$_HasEnum) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? byName = null,
Object? byValue = null,
}) {
return _then(_$_HasEnum(
byName: null == byName
? _value.byName
: byName // ignore: cast_nullable_to_non_nullable
as ByName,
byValue: null == byValue
? _value.byValue
: byValue // ignore: cast_nullable_to_non_nullable
as ByValue,
));
}
}
/// @nodoc
@JsonSerializable(fieldRename: FieldRename.snake, explicitToJson: true)
class _$_HasEnum implements _HasEnum {
const _$_HasEnum({required this.byName, required this.byValue});
factory _$_HasEnum.fromJson(Map<String, dynamic> json) =>
_$$_HasEnumFromJson(json);
@override
final ByName byName;
@override
final ByValue byValue;
@override
String toString() {
return 'HasEnum(byName: $byName, byValue: $byValue)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_HasEnum &&
(identical(other.byName, byName) || other.byName == byName) &&
(identical(other.byValue, byValue) || other.byValue == byValue));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, byName, byValue);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_HasEnumCopyWith<_$_HasEnum> get copyWith =>
__$$_HasEnumCopyWithImpl<_$_HasEnum>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$_HasEnumToJson(
this,
);
}
}
abstract class _HasEnum implements HasEnum {
const factory _HasEnum(
{required final ByName byName,
required final ByValue byValue}) = _$_HasEnum;
factory _HasEnum.fromJson(Map<String, dynamic> json) = _$_HasEnum.fromJson;
@override
ByName get byName;
@override
ByValue get byValue;
@override
@JsonKey(ignore: true)
_$$_HasEnumCopyWith<_$_HasEnum> get copyWith =>
throw _privateConstructorUsedError;
} |
@kzrnm Yup, your code is definitely working as expected. I had some toJson()'s living in extensions somewhere that weren't being picked up. I moved all the toJson()'s into the enums and now its functional. I'm still not sure why the old versions worked and the new one didn't though. |
This doesn't work if I am using @JsonValue from json_serializable package. It still uses |
Vesion 7.0.7 has breaking change.
I want to use
toJson()
if it exists.7.0.6 and 7.0.8 generates
final queryParameters = <String, dynamic>{r'test': status?.toJson()};
.7.0.7 generates
final queryParameters = <String, dynamic>{r'test': status?.name};
.