← → or space · progress saves for Continue on the roadmap
Goal
Implement manual serialization for two models used together.
Step 1 - User
class User {
final String id;
final String name;
final String? email;
User({required this.id, required this.name, this.email});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'] as String,
name: json['name'] as String,
email: json['email'] as String?,
);
}
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'email': email,
};
}Step 2 - Todo (with userId)
class Todo {
final String id;
final String title;
final bool done;
final String userId;
Todo({
required this.id,
required this.title,
this.done = false,
required this.userId,
});
factory Todo.fromJson(Map<String, dynamic> json) {
return Todo(
id: json['id'] as String,
title: json['title'] as String,
done: json['done'] as bool? ?? false,
userId: json['userId'] as String,
);
}
Map<String, dynamic> toJson() => {
'id': id,
'title': title,
'done': done,
'userId': userId,
};
}
void main() {
final u = User(id: 'u1', name: 'Asha', email: 'a@b.com');
final t = Todo(id: 't1', title: 'Learn JSON', userId: u.id);
print(t.toJson());
}Practice tasks
- Add
DateTime? dueAtstored in JSON as ISO-8601 strings (toIso8601String/DateTime.tryParse). - Round-trip:
jsonEncodethenjsonDecodethenTodo.fromJsonand assert fields match. - Omit
emailfromtoJsonwhen null (use a small map built with conditional entries).