Flutter客户端:如何将MongoDB返回的List<dynamic>转为List<Object>
解决方案
问题根源
- 服务端直接发送Mongoose查询结果时,返回的是Mongoose文档实例而非纯JSON对象,这些实例携带额外的Mongoose内部属性,导致客户端解析后的数据结构不符合预期。
- 客户端直接用
cast<Object>()无法将动态列表转为自定义对象列表——列表中的元素是JSON解析后的Map<String, dynamic>,不是业务对象实例,强制类型转换会触发类型不匹配异常。
步骤1:服务端返回纯JSON数据
修改Node.js服务端代码,让Mongoose返回普通JavaScript对象,有两种实现方式:
方式一:使用lean()(推荐,性能更高)
lean()会跳过Mongoose文档实例的创建过程,直接返回原始JSON对象:
socket.on("event", async() => { // 使用lean()获取纯JS对象数组 var objectList = await Model.find().lean(); socket.emit("event", objectList); });
方式二:手动转换为JSON
如果无法使用lean(),可以将每个文档实例转为纯JSON:
socket.on("event", async() => { var objectList = await Model.find(); // 将Mongoose文档转为纯JSON对象 const plainObjects = objectList.map(doc => doc.toJSON()); socket.emit("event", plainObjects); });
步骤2:客户端解析为自定义对象列表
在Flutter中,先定义与MongoDB文档结构对应的实体类,再将收到的动态列表逐个转换为实体类实例。
示例:定义实体类
假设你的MongoDB文档包含_id和name字段,创建对应Dart类:
class MyBusinessObject { final String id; final String name; MyBusinessObject({required this.id, required this.name}); // 从Map<String, dynamic>转换为实体类 factory MyBusinessObject.fromJson(Map<String, dynamic> json) { return MyBusinessObject( id: json['_id'], // MongoDB默认主键字段是_id name: json['name'], // 根据你的文档结构添加其他字段的解析逻辑 ); } }
客户端处理SocketIO数据
替换原来的cast方式,遍历动态列表并转换为实体类:
_socketClient?.on("event", (objectList) { // 先校验数据类型 if (objectList is List) { List<MyBusinessObject> convertedList = objectList.map((item) { // 将每个Map元素转换为实体类实例 return MyBusinessObject.fromJson(item as Map<String, dynamic>); }).toList(); // 这里convertedList就是你需要的强类型列表 // 后续可直接用于业务逻辑 } else { print("收到的数据不是预期的列表格式"); } });
异常说明
你遇到的type 'List<dynamic>' is not a subtype of type 'String'异常,大概率是服务端发送非纯JSON数据导致客户端解析异常,或代码中其他地方误将列表当作字符串处理。按上述步骤修改后,该异常会消失。
内容的提问来源于stack exchange,提问作者user29365632
相关产品推荐
相关产品推荐

