如何解决Dart Flutter通用Api响应类动态类数据类型
我的应用当前正在为每个api响应作为模型使用自定义类。 但是我试图对其进行更改,以优化一些小事情,因此我试图实现一个类包装器,例如,称为ApiResponse。 但是对于fromJson和toJson的make来说,静态调用和方法无法正常工作。
例如,我将展示我的尝试。 MyModel->类响应。 ApiResponse->主类,内部包含任何模型类,并且必须作为子方法本身称为“ fromjson / tojson”。 测试->用于测试的类,在类上有错误注释。
class MyModel {
String id;
String title;
MyModel({this.id,this.title});
factory MyModel.fromJson(Map<String,dynamic> json) {
return MyModel(
id: json["id"],title: json["title"],);
}
Map<String,dynamic> toJson() => {
"id": this.id,"title": this.title,};
}
class ApiResponse<T> {
bool status;
String message;
T data;
ApiResponse({this.status,this.message,this.data});
factory ApiResponse.fromJson(Map<String,dynamic> json) {
return ApiResponse<T>(
status: json["status"],message: json["message"],data: (T).fromJson(json["data"])); // The method 'fromJson' isn't defined for the type 'Type'.
// Try correcting the name to the name of an existing method,or defining a method named 'fromJson'.
}
Map<String,dynamic> toJson() => {
"status": this.status,"message": this.message,"data": this.data.toJson(),// The method 'toJson' isn't defined for the type 'Object'.
// Try correcting the name to the name of an existing method,or defining a method named 'toJson'
};
}
class Test {
test() {
ApiResponse apiResponse = ApiResponse<MyModel>();
var json = apiResponse.toJson();
var response = ApiResponse<MyModel>.fromJson(json);
}
}
解决方法
您不能在Dart上的类型上调用方法,因为静态方法必须在编译时解析,并且类型在运行时之前没有值。
但是,您可以将解析器回调传递给构造函数,并使用每个模型都可以实现的接口(例如Serializable
)。然后,通过将您的ApiResponse
更新为ApiResponse<T extends Serializable>
,它将知道每种类型T
都有一个toJson()
方法。
这里是完整的示例。
class MyModel implements Serializable {
String id;
String title;
MyModel({this.id,this.title});
factory MyModel.fromJson(Map<String,dynamic> json) {
return MyModel(
id: json["id"],title: json["title"],);
}
@override
Map<String,dynamic> toJson() => {
"id": this.id,"title": this.title,};
}
class ApiResponse<T extends Serializable> {
bool status;
String message;
T data;
ApiResponse({this.status,this.message,this.data});
factory ApiResponse.fromJson(Map<String,dynamic> json,Function(Map<String,dynamic>) create) {
return ApiResponse<T>(
status: json["status"],message: json["message"],data: create(json["data"]),);
}
Map<String,dynamic> toJson() => {
"status": this.status,"message": this.message,"data": this.data.toJson(),};
}
abstract class Serializable {
Map<String,dynamic> toJson();
}
class Test {
test() {
ApiResponse apiResponse = ApiResponse<MyModel>();
var json = apiResponse.toJson();
var response = ApiResponse<MyModel>.fromJson(json,(data) => MyModel.fromJson(data));
}
}
,
base_response.dart
class BaseResponse {
dynamic message;
bool success;
BaseResponse(
{this.message,this.success});
factory BaseResponse.fromJson(Map<String,dynamic> json) {
return BaseResponse(
success: json["success"],message: json["message"]);
}
}
list_response.dart
server response for list
{
"data": []
"message": null,"success": true,}
class ListResponse<T> extends BaseResponse {
List<T> data;
ListResponse({
String message,bool success,this.data,}) : super(message: message,success: success);
factory ListResponse.fromJson(Map<String,dynamic>) create) {
var data = List<T>();
json['data'].forEach((v) {
data.add(create(v));
});
return ListResponse<T>(
success: json["success"],data: data);
}
}
single_response.dart
server response for single object
{
"data": {}
"message": null,}
class SingleResponse<T> extends BaseResponse {
T data;
SingleResponse({
String message,success: success);
factory SingleResponse.fromJson(Map<String,dynamic>) create) {
return SingleResponse<T>(
success: json["success"],data: create(json["data"]));
}
}
data_response.dart
class DataResponse<T> {
Status status;
T res; //dynamic
String loadingMessage;
GeneralError error;
DataResponse.init() : status = Status.Init;
DataResponse.loading({this.loadingMessage}) : status = Status.Loading;
DataResponse.success(this.res) : status = Status.Success;
DataResponse.error(this.error) : status = Status.Error;
@override
String toString() {
return "Status : $status \n Message : $loadingMessage \n Data : $res";
}
}
enum Status {
Init,Loading,Success,Error,}
或者如果使用 freeezed 那么 data_response 可以是
@freezed
abstract class DataResponse<T> with _$DataResponse<T> {
const factory DataResponse.init() = Init;
const factory DataResponse.loading(loadingMessage) = Loading;
const factory DataResponse.success(T res) = Success<T>;
const factory DataResponse.error(GeneralError error) = Error;
}
用法:(retrofit 库和 retrofit_generator 自动生成代码的一部分)
const _extra = <String,dynamic>{};
final queryParameters = <String,dynamic>{};
final _data = <String,dynamic>{};
final _result = await _dio.request<Map<String,dynamic>>('$commentID',queryParameters: queryParameters,options: RequestOptions(
method: 'GET',headers: <String,dynamic>{},extra: _extra,baseUrl: baseUrl),data: _data);
final value = SingleResponse<Comment>.fromJson(
_result.data,(json) => Comment.fromJson(json),);
,
There is another way,Map<String,dynamic> toJson() => {
"message": message,"status": status,"data": _toJson<T>(data),};
static T _fromJson<T>(Map<String,dynamic> json) {
return ResponseModel.fromJson(json) as T;
}
,
您可以尝试我的方法来应用通用响应:APIResponse<MyModel>
通过实现自定义的 Decodable 抽象类,来自 http 请求的响应将作为 MyModel
对象返回。
Future<User> fetchUser() async {
final client = APIClient();
final result = await client.request<APIResponse<User>>(
manager: APIRoute(APIType.getUser),create: () => APIResponse<User>(create: () => User())
);
final user = result.response.data; // reponse.data will map with User
if (user != null) {
return user;
}
throw ErrorResponse(message: 'User not found');
}
这是我的源代码: https://github.com/katafo/flutter-generic-api-response
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。