My app currently is working with a custom classes for each API responses as models.
But I'm trying to change it, to optimize some little things, so I'm trying to implement a Class wrapper, called ApiResponse
for example.
But its not working fine the static call and methods, for make fromJson
and toJson
.
I will show what I'm trying, as example.
MyModel -> class response.
ApiResponse -> main class that contains any model class inside, and must be call child methods as itselfs 'fromjson/tojson'.
Test -> class for test purpose, errors comments on 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);
}
}
You can't call methods on types on Dart because static methods must be resolved at compile time and types do not have a value until runtime.
You can, however, pass a parser callback to your constructor and use an interface(eg. Serializable
) that every model may implement. Then, by updating your ApiResponse
to ApiResponse<T extends Serializable>
it will know that every type T
will have a toJson()
method.
Here's the full example updated.
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));
}
}