retrofit.dart
retrofit.dart copied to clipboard
How to deal with generic data?
import 'package:json_annotation/json_annotation.dart'; part 'BaseResponse.g.dart';
@JsonSerializable() class BaseResponse<T> { int? errorCode; String? errorMsg; T? data;
BaseResponse({ this.errorCode, this.errorMsg, this.data, });
factory BaseResponse.fromJson(Map<String, dynamic> srcJson) => _$BaseResponseFromJson(srcJson);
Map<String, dynamic> toJson() => _$BaseResponseToJson(this); }
Could not generate fromJson
code for data
because of type T
(type parameter).
How to use this generic data 'BaseResponse'?
@hc79879 U need to use converter for this.
Check code below for the answer.
@JsonSerializable()
class ApiResponse<T> {
@_Converter()
final T? result;
final String resultCode;
final String? resultMessage;
ApiResponse({this.result, required this.resultCode, this.resultMessage});
factory ApiResponse.fromJson(Map<String, dynamic> json) =>
_$ApiResponseFromJson(json);
Map<String, dynamic> toJson() => _$ApiResponseToJson(this);
@override
String toString() {
return "$resultCode: $resultMessage";
}
}
// generic list converter
class _Converter<T> implements JsonConverter<T?, Object?> {
const _Converter();
@override
T fromJson(Object? json) {
if (json == null) return null as T;
if (typesEqual<T, String?>()) {
return json as T;
} else if (typesEqual<T, AuthToken?>()) {
return AuthToken.fromJson(json as Map<String, dynamic>) as T;
}
// note : currently dart does not support generic type checking without explicit definition of generic type.
throw FormatException("No valid structure for json $json");
}
@override
Object? toJson(T? object) {
// This will only work if `object` is a native JSON type:
// num, String, bool, null, etc
// Or if it has a `toJson()` function`.
return object as Map<String, dynamic>?;
}
}
There's no need for converter, just enable genericArgumentFactories
in JsonSerializable
@JsonSerializable(
constructor: '_',
createToJson: false,
genericArgumentFactories: true,
)
class Page<T extends Object> {
final int limit;
final int total;
final List<T> items;
Page._(this.limit, this.total, this.items);
factory Page.fromJson(Map<String, dynamic> json, T Function(Object? json) fromJsonT) => _$PageFromJson(json, fromJsonT);
}
and if I didn't forget anything, this should be enough.
Of course your T
must also be JsonSerializable
enabled.
how can I use this if I use?
@RestApi(parser: Parser.FlutterCompute)
@trevorwang Please add generic support for Parser.FlutterCompute. It should accept optional additional argument
T Function(Object? json) fromJsonT