Book model part 3
Data Layer
Summary
This lesson integrates the BookModel into the Clean Architecture flow by establishing an inheritance relationship with BookEntity. By having the model extend the entity, the data layer can seamlessly return model instances to the domain layer, which then treats them as standard entities. The lesson covers updating the entity with required domain fields, and then mapping the complex, deep API JSON structure into these simplified fields via the model's super constructor.
Key Ideas
- Models must inherit from Entities (BookModel extends BookEntity) to satisfy the repository contract in the domain layer.
- Inheritance guarantees that the domain layer only interacts with the generic entity fields, safely hiding data-source-specific JSON serialization details.
- The super constructor in Dart is utilized to pass parsed JSON data from the child model up to the parent entity's properties.
- Naming conflicts between the Model and Entity (like the id field) can be resolved by uniquely naming the Entity's field (e.g., bookId) to avoid forced overrides.
- Null safety requires careful handling when mapping deep JSON objects to entity fields, utilizing the null-coalescing operator (??) to provide fallbacks.
Code Snippets
class BookEntity {
final String bookId;
final String? image;
final String title;
final String? authorName;
final num? price;
final num? rating;
BookEntity({
required this.image,
required this.title,
required this.authorName,
required this.price,
required this.rating,
required this.bookId,
});
}class BookModel extends BookEntity {
String? kind;
String? id;
String? etag;
String? selfLink;
VolumeInfo? volumeInfo;
SaleInfo? saleInfo;
AccessInfo? accessInfo;
SearchInfo? searchInfo;
BookModel({
this.kind,
this.id,
this.etag,
this.selfLink,
this.volumeInfo,
this.saleInfo,
this.accessInfo,
this.searchInfo,
}) : super(
bookId: id!,
image: volumeInfo!.imageLinks?.thumbnail ?? '',
authorName: volumeInfo.authors?.first,
price: 0.0,
rating: volumeInfo.averageRating,
title: volumeInfo.title!,
);
// factory BookModel.fromJson(...) remains below
}My Notes
The instructor explicitly changes the id field in the entity to bookId to avoid overriding conflicts with the id field generated by the JSON-to-Dart tool in the BookModel. This is a practical way to sidestep complex getter/setter overrides in Dart when mixing domain entities with auto-generated DTOs. [Editor's note] Be extremely careful with the bang operator (!) used on the fields in the super constructor (e.g., volumeInfo.title! and id!). If the Google Books API returns an item missing a title or an ID, your app will encounter a fatal Null check operator used on a null value runtime exception. A much safer production approach for the title would be title: volumeInfo?.title ?? 'Unknown Title'.