如何在Dart/Flutter中将自定义Card保存到Shared Preferences
序列化与反序列化FSRS的Card对象
问题核心
FSRS库的Card类未内置JSON序列化支持,直接调用json.encode(card)会报错;通过card.toString()得到的字符串虽类似JSON,但需要额外处理才能还原为Card对象。
推荐解决方案:实现可靠的序列化/反序列化逻辑
不要依赖toString()的输出(格式可能随库更新变化),而是通过辅助函数将Card转为可序列化的Map,再实现从Map重建Card的逻辑,这样既兼容json.encode也方便存入Firestore。
1. 序列化Card到JSON
编写辅助函数将Card转为Map<String, dynamic>,再用json.encode处理:
import 'package:fsrs/fsrs.dart'; import 'dart:convert'; Map<String, dynamic> cardToJson(Card card) { return { 'due': card.due.toIso8601String(), 'stability': card.stability, 'difficulty': card.difficulty, 'elapsedDays': card.elapsedDays, 'scheduledDays': card.scheduledDays, 'reps': card.reps, 'lapses': card.lapses, 'state': card.state.toString().split('.').last, // 提取枚举值名称(如"newState") 'lastReview': card.lastReview?.toIso8601String(), }; } // 使用示例 void serializeCard() { var f = FSRS(); var card = Card(); var now = DateTime(2022, 11, 29, 12, 30, 0, 0); f.repeat(card, now); var encoded = json.encode(cardToJson(card)); print(encoded); // 标准JSON格式,可直接存入Firestore或SharedPreferences }
2. 从JSON还原Card对象
编写辅助函数从解析后的Map重建Card,处理DateTime和State枚举的转换:
Card cardFromJson(Map<String, dynamic> json) { return Card( due: DateTime.parse(json['due']), stability: json['stability'], difficulty: json['difficulty'], elapsedDays: json['elapsedDays'], scheduledDays: json['scheduledDays'], reps: json['reps'], lapses: json['lapses'], state: State.values.firstWhere( (e) => e.toString().split('.').last == json['state'], orElse: () => State.newState, // 兜底默认值 ), lastReview: json['lastReview'] != null ? DateTime.parse(json['lastReview']) : null, ); } // 使用示例 void deserializeCard(String encodedJson) { var decodedMap = json.decode(encodedJson); var restoredCard = cardFromJson(decodedMap); print(restoredCard); // 还原后的Card对象 }
兼容已存的toString格式数据
如果已经通过card.toString()存储了数据,需要先解码外层字符串,再解析JSON:
void restoreFromToStringData(String encodedString) { // 先解码外层的JSON字符串(去掉包裹的引号) var rawJsonStr = json.decode(encodedString); // 再解析为Map var cardMap = json.decode(rawJsonStr); // 还原Card var restoredCard = cardFromJson(cardMap); }
内容的提问来源于stack exchange,提问作者My Name
相关产品推荐
相关产品推荐

