'How create model in data layer for entities when get list of entities from data source in clean architecture

I follow clean architecture for a simple showing contacts project. In my flutter project, I have these directories: Data, Domain, Presentation. I started by creating an entity for a sample contact in the Domain layer

class Contact {
  final String fullName;
  final String email;
  final bool favourite;

  Contact(
      {required this.fullName, required this.email, required this.favourite});
}

When we get contacts from data sources it usually is in form of List<Contact> like this JSON response

{
  "contacts": [
    {
      "fullName" : "John Doe (JSON)",
      "email" : "[email protected]",
      "favourite" : true
    },
    {
      "fullName" : "Ema Doe (JSON)",
      "email" : "[email protected]",
      "favourite" : false
    },
    {
      "fullName" : "Micheal Roe (JSON)",
      "email" : "[email protected]",
      "favourite" : false
    }
  ]
}

Now the question is how we implement the model in the Data layer which would be correct based on clean architecture. Is this model correct?

class ContactsModel {
  late List<Contact> contacts;

  ContactsModel({required this.contacts});

  ContactsModel.fromJson(dynamic json) {
    if (json['contacts'] != null) {
      contacts = [];
      json['contacts'].forEach((v) {
        contacts.add(ContactModel.fromJson(v));
      });
    }
  }
}

class ContactModel extends Contact {
  ContactModel(
      {required String fullName,
      required String email,
      required bool favourite})
      : super(fullName: fullName, email: email, favourite: favourite);

  ContactModel.fromJson(dynamic json)
      : super(
          fullName: json['fullName'],
          email: json['email'],
          favourite: json['favourite'],
        );
}



Solution 1:[1]

use List of Contact as the model class. In your domain layer here is your entity

class Contact extends Equatable {
  final String fullName;
  final String email;
  final bool favourite;

  Contact(
      {required this.fullName, required this.email, required this.favourite});

  @override
  List<Object?> get props => [fullName, email, favourite];
}

And here is your ContactModel in the Data layer


class ContactsModel {
  List<Contact> contacts = [];

  ContactsModel({required this.contacts});

  ContactsModel.fromJson(Map<String, dynamic> json) {
    if (json['contacts'] != null) {
      json['contacts'].forEach((v) {
        contacts.add(ContactModel.fromJson(v));
      });
    }
  }

  ContactsModel.fromXml(XmlDocument xmlDocument) {
    contacts = [];
    for (XmlElement xmlElement in xmlDocument.findAllElements('contact')) {
      contacts.add(ContactModel.fromXml(xmlElement));
    }
  }

  @override
  List<Object?> get props => [contacts];
}
class ContactModel extends Contact {
  ContactModel(
      {required String fullName,
      required String email,
      required bool favourite})
      : super(fullName: fullName, email: email, favourite: favourite);

  ContactModel.fromJson(Map<String, dynamic> json)
      : super(
          fullName: json['fullName'],
          email: json['email'],
          favourite: json['favourite'],
        );

  ContactModel.fromXml(XmlElement xmlElement)
      : super(
          fullName: xmlElement.findElements('fullName').single.text.trim(),
          email: xmlElement.findElements('email').single.text.trim(),
          favourite: xmlElement
                  .findElements('favourite')
                  .single
                  .text
                  .toLowerCase()
                  .trim() ==
              'true',
        );
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 zex_rectooor