Reputation: 683
I am trying to use clean architecture (explained by reso coder: https://resocoder.com/2019/09/09/flutter-tdd-clean-architecture-course-4-data-layer-overview-models/) in my project.
In his example, he implements an entity and a model extending the entity. The entity has all of the properties and the model implements the fromJson and toJson Methods.
It works well with "flat" classes.
But now I want to implement that for a class that has a list of other classes.
class Item {
String text;
}
class ItemModel extends Item{
...toJson
...romJson
}
class Order {
...
List<Item> items;
}
class OrderModel extends Item {
...
...fromJson() {
if (json['items'] != null) {
teams = new List<ItemModel>();
json['items'].forEach((v) {
items.add(Item.fromJson(v));
});
}
}
}
...toJson(){
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.items!= null) {
data['items'] = this.items.map((v) => v.toJson()).toList();
}
return data;
}
Of course it doesn´t work, because the class item does not have a method "toJson".
What is the correct way to implement it? Cast the List to List in the toJson method.
EDIT
When I try to cast the list items to ItemModel and there is an Item in the list, then an exception is thrown:
type 'Item' is not a subtype of type 'ItemModel' in type cast
I would now consider the following to be correct: Add a factory method to the ItemModel that cast an Item to an ItemModel:
fromItem(Item item){
if(item is ItemModel) {
return item as ItemModel;
}
return ItemModel(..: item...);
}
Is that the best way to solve this?
Upvotes: 4
Views: 1063
Reputation: 683
I now solved it in the following way.
I´ve added a method to the model class to cast the entity to the model
factory ItemModel.fromItem(Item item) {
if (item is ItemModel) {
return item;
}
return ItemModel(
text: item.text,
);
}
And adapted the toJson method
...toJson(){
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.items != null) {
data['items'] = this.items.map((v) => ItemModel.fromItem(v).toJson()).toList();
}
return data;
}
Upvotes: 2
Reputation: 4763
You are using Item.fromJson
instead of ItemModel.fromJson
? Have you tried this ?
class OrderModel extends Item {
...
...fromJson() {
if (json['items'] != null) {
teams = new List<ItemModel>();
json['items'].forEach((v) {
items.add(ItemModel.fromJson(v));
});
}
}
}
Edit
If you to call toJson on Item directly, you can cast it's value to ItemModel as following
...toJson(){
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.items != null) {
data['items'] = this.items.map((v) => (v as ItemModel).toJson()).toList();
}
return data;
}
Edit 2
Make your Item class abstract and add abstract methods fromJson a and toJson
abstract class Item {
//...
Item fromJson(Map json); // abstract method
Map<String, dynamic> toJson(); // abstract method
}
Upvotes: 1