clean architecture toJson with sublist (reso coder)

284

Solution 1

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;
}

Solution 2

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
   
}
Share:
284
A.K.
Author by

A.K.

My profession and my passion is programming

Updated on December 26, 2022

Comments

  • A.K.
    A.K. over 1 year

    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 implements that for a class that has a list of another class.

    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 doenn´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?

  • A.K.
    A.K. over 3 years
    Wow, this Day was to long.
  • A.K.
    A.K. over 3 years
    sorry i have posted the wrong method. The fromJson method ist ok. but i have the problem with toJson
  • A.K.
    A.K. over 3 years
    ok, but is it ok to cast it without any checks? It could be possible that there is an Item in that list without the toJson method.
  • dm_tr
    dm_tr over 3 years
    Boss, ItemModel directly extends Item. I can't any problem casting Item to ItemModel
  • dm_tr
    dm_tr over 3 years
    Another way is my using abstract method in your Item class. So that any class extending it must implement ..fromJson and ..toJson
  • A.K.
    A.K. over 3 years
    hi, i changed my question, because your solution throws an exception.
  • dm_tr
    dm_tr over 3 years
    This is only possible when you create abstract methods in your class Item
  • A.K.
    A.K. over 3 years
    Hmm, i dont like your solution. I think it´s not the way clean architecture handles Entities and Models.
  • dm_tr
    dm_tr over 3 years
    So unless you change items type in OrderModel to List<ItemModel> items;, otherwise what you are trying to do is not possible
  • A.K.
    A.K. over 3 years
    I try to understand how this has to be handled in reso coders clean architecture. The Datasources returning the model classses and the repositories the entities. The entities are not abstract and the the entities extending the models. The entities dont have toJson or FromJson methods..Thats the starting situation. From this situation I try to understand how to implement a entitiy with a child list the right way.
  • w461
    w461 almost 3 years
    Hi, is your solution still your preferred way or did you meanwhile came up with something more "elegant"? I just created a similar question here: stackoverflow.com/questions/68624601/…
  • A.K.
    A.K. almost 3 years
    Hi, yes, it´s still my preferred way.
  • miloskarakas
    miloskarakas about 2 years
    @A.K. Same here, I had no other way of doing it. It makes sense since the model should be responsible for all data conversions. Thanks for putting your answer here, you confirmed my approach.
  • miloskarakas
    miloskarakas about 2 years
    I just named it fromBase to make it uniform across all models