json property
Factory constructor for creating instances from Firestore data.
This constructor is called by FirestorePlus when deserializing documents from Firestore. It should handle all the type casting and validation needed to create a properly typed instance.
Example
static User withMap(Map<String, dynamic> map) => User(
uid: map['uid'],
name: map['name'] ?? '',
email: map['email'] ?? '',
age: (map['age'] as num?)?.toInt() ?? 0,
isActive: map['isActive'] ?? false,
);
Type Safety
Always handle type casting safely:
- Use
as numfor numbers, then convert to specific types - Provide default values for nullable fields
- Validate required fields
Error Handling
Consider adding validation:
static User withMap(Map<String, dynamic> map) {
if (map['name'] == null) {
throw ArgumentError('Name is required');
}
return User(
uid: map['uid'],
name: map['name'],
email: map['email'] ?? '',
);
}
Note: Each implementing class should provide a static withMap method.
JSON serialization for Firestore storage.
This getter converts the model instance to a Map that can be stored in Firestore. It should include all the data that needs to be persisted.
Example
@override
Map<String, dynamic> get json => {
'uid': uid,
'name': name,
'email': email,
'createdAt': createdAt?.toIso8601String(),
'isActive': isActive,
'preferences': preferences.toJson(),
};
Best Practices
- Include the
uidfield for document identification - Convert complex types to serializable formats (e.g., DateTime to String)
- Handle nested objects by calling their serialization methods
- Use consistent field names that match your Firestore schema
- Consider excluding computed properties that can be derived
Performance Considerations
- This getter is called frequently during write operations
- Keep the serialization logic simple and efficient
- Avoid expensive computations in this getter
- Consider caching if the serialization is complex
Implementation
/// JSON serialization for Firestore storage.
///
/// This getter converts the model instance to a Map that can be stored
/// in Firestore. It should include all the data that needs to be persisted.
///
/// ## Example
///
/// ```dart
/// @override
/// Map<String, dynamic> get json => {
/// 'uid': uid,
/// 'name': name,
/// 'email': email,
/// 'createdAt': createdAt?.toIso8601String(),
/// 'isActive': isActive,
/// 'preferences': preferences.toJson(),
/// };
/// ```
///
/// ## Best Practices
///
/// 1. Include the `uid` field for document identification
/// 2. Convert complex types to serializable formats (e.g., DateTime to String)
/// 3. Handle nested objects by calling their serialization methods
/// 4. Use consistent field names that match your Firestore schema
/// 5. Consider excluding computed properties that can be derived
///
/// ## Performance Considerations
///
/// - This getter is called frequently during write operations
/// - Keep the serialization logic simple and efficient
/// - Avoid expensive computations in this getter
/// - Consider caching if the serialization is complex
Map<String, dynamic> get json;