使用Dart将含对象的Map序列化为JSON时遇错求助
解决Dart中json_serializable序列化Map<自定义对象, 值>的问题
你遇到的错误核心原因是JSON规范不支持非字符串类型作为对象的键,直接序列化Map<PlayerModel, double>时,PlayerModel无法被识别为合法的JSON键,因此抛出JsonUnsupportedObjectError。下面提供两种可行的解决方案:
方案一:将Map转换为包含完整Player信息的数组(推荐,无需依赖外部数据)
这种方式把原Map结构转换成JSON支持的数组格式,每个元素包含Player的完整JSON数据和对应分数,序列化后可以独立还原,无需依赖外部的Player数据源。
修改BoardDataConverter的实现:
class BoardDataConverter implements JsonConverter<Map<PlayerModel, double>, List<dynamic>> { const BoardDataConverter(); @override Map<PlayerModel, double> fromJson(List<dynamic> jsonList) { final Map<PlayerModel, double> result = {}; for (final item in jsonList) { final player = PlayerModel.fromJson(item['player'] as Map<String, dynamic>); final score = item['score'] as double; result[player] = score; } return result; } @override List<dynamic> toJson(Map<PlayerModel, double> data) { return data.entries.map((entry) => { 'player': entry.key.toJson(), 'score': entry.value, }).toList(); } }
修改后,boardData字段的注解保持不变,重新运行build_runner更新生成文件:
flutter pub run build_runner build
方案二:用Player的唯一ID作为JSON键(适合已有Player数据源的场景)
如果你的业务中已经有全局的Player列表/缓存,可以用Player的id(唯一标识)作为JSON中的键,节省存储空间,但反序列化时需要根据ID还原Player实例。
修改BoardDataConverter的实现:
class BoardDataConverter implements JsonConverter<Map<PlayerModel, double>, Map<String, dynamic>> { const BoardDataConverter(); // 需实现根据ID获取PlayerModel的逻辑(比如从数据库/缓存中查询) PlayerModel _getPlayerById(String id) { // 示例逻辑,根据实际业务替换 // return PlayerCache.instance.getPlayer(id); throw UnimplementedError('请实现根据ID获取PlayerModel的方法'); } @override Map<PlayerModel, double> fromJson(Map<String, dynamic> jsonMap) { final Map<PlayerModel, double> result = {}; for (final entry in jsonMap.entries) { final player = _getPlayerById(entry.key); final score = entry.value as double; result[player] = score; } return result; } @override Map<String, dynamic> toJson(Map<PlayerModel, double> data) { final Map<String, double> jsonMap = {}; for (final entry in data.entries) { jsonMap[entry.key.id] = entry.value; } return jsonMap; } }
同样,重新运行build_runner更新生成的.g文件即可。
关键注意事项
- 无论哪种方案,都要确保
PlayerModel的toJson和fromJson方法能正常工作(你的代码中已经实现,没问题)。 - 方案一中,序列化后的JSON会包含Player的完整数据,适合需要独立存储BoardModel的场景;方案二更轻量化,但依赖外部的Player数据源。
内容的提问来源于stack exchange,提问作者CSF90
相关产品推荐
相关产品推荐

