Dart Flutter 通用 Api 响应 Class 动态 Class 数据类型
Dart Flutter Generic Api Response Class Dynamic Class Data Type
我的应用目前正在使用自定义 classes 作为模型的每个 api 响应。
但我试图改变它,优化一些小东西,所以我试图实现一个 Class 包装器,例如称为 ApiResponse。
但是对于 make fromJson 和 toJson,它的静态调用和方法不能正常工作。
我会展示我正在尝试的东西,例如。
MyModel -> class 响应。
ApiResponse -> main class 包含任何模型 class 内部,并且必须调用子方法本身 'fromjson/tojson'。
测试 -> class 用于测试目的,错误评论 classes.
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,
}
@JsonSerializable(genericArgumentFactories: 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> json, Function(Map<String, dynamic>) create) {
var data = List<T>();
json['data'].forEach((v) {
data.add(create(v));
});
return ListResponse<T>(
success: json["success"],
message: json["message"],
data: data);
}
}
single_response.dart
server response for single object
{
"data": {}
"message": null,
"success": true,
}
@JsonSerializable(genericArgumentFactories: true)
class SingleResponse<T> extends BaseResponse {
T data;
SingleResponse({
String message,
bool success,
this.data,
}) : super(message: message, success: success);
factory SingleResponse.fromJson(Map<String, dynamic> json, Function(Map<String, dynamic>) create) {
return SingleResponse<T>(
success: json["success"],
message: json["message"],
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 library and 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 抽象 class,http 请求的响应将 return 作为 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
我的应用目前正在使用自定义 classes 作为模型的每个 api 响应。 但我试图改变它,优化一些小东西,所以我试图实现一个 Class 包装器,例如称为 ApiResponse。 但是对于 make fromJson 和 toJson,它的静态调用和方法不能正常工作。
我会展示我正在尝试的东西,例如。 MyModel -> class 响应。 ApiResponse -> main class 包含任何模型 class 内部,并且必须调用子方法本身 'fromjson/tojson'。 测试 -> class 用于测试目的,错误评论 classes.
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,
}
@JsonSerializable(genericArgumentFactories: 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> json, Function(Map<String, dynamic>) create) {
var data = List<T>();
json['data'].forEach((v) {
data.add(create(v));
});
return ListResponse<T>(
success: json["success"],
message: json["message"],
data: data);
}
}
single_response.dart
server response for single object
{
"data": {}
"message": null,
"success": true,
}
@JsonSerializable(genericArgumentFactories: true)
class SingleResponse<T> extends BaseResponse {
T data;
SingleResponse({
String message,
bool success,
this.data,
}) : super(message: message, success: success);
factory SingleResponse.fromJson(Map<String, dynamic> json, Function(Map<String, dynamic>) create) {
return SingleResponse<T>(
success: json["success"],
message: json["message"],
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 library and 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 抽象 class,http 请求的响应将 return 作为 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