You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 22:52:24