Flutter Firebase解析异常:'String'不是'index'的'int'子类型
问题:Firebase Realtime Database数据解析异常:
type 'String' is not a subtype of type 'int' of 'index' 尝试从Firebase Realtime Database获取数据(数据路径为2129 -> 911),能正常获取到JSON响应,但使用自定义模型类UserDataModel解析时抛出异常:
User Data Error: type 'String' is not a subtype of type 'int' of 'index'
Firebase数据结构
{ "2129": { "911": { "TimeStamp": 1657782900738, "connectedStatus": "Requested", "imagePath": "https://www.ppp.in/placeholder.png", "lastMessage": "", "status": "Active", "time": "2022-07-14 12:45:00", "typing": false }, "xxx": { "imagePath": "https://asd-123.jpg", "lastMessage": "hi", "typing": false, "connectedStatus": "Pending", "unreadMessageCount": 0, "time": "2022-07-21 16:22:58", "userId": 2277, "TimeStamp": 1658400778129, "status": "Unactive", "username": "Users Name" } } }
自定义模型类UserDataModel代码
UserDataModel mUserIdFromJson(String str) => UserDataModel.fromJson(json.decode(str)); String mUserIdToJson(UserDataModel data) => json.encode(data.toJson()); class UserDataModel { UserDataModel({ String? imagePath, String? lastMessage, bool? typing, String? connectedStatus, int? unreadMessageCount, String? time, int? userId, int? timeStamp, String? status, String? username,}){ _imagePath = imagePath; _lastMessage = lastMessage; _typing = typing; _connectedStatus = connectedStatus; _unreadMessageCount = unreadMessageCount; _time = time; _userId = userId; _timeStamp = timeStamp; _status = status; _username = username; } UserDataModel.fromJson(dynamic json) { _imagePath = json['imagePath']; _lastMessage = json['lastMessage']; _typing = json['typing']; _connectedStatus = json['connectedStatus']; _unreadMessageCount = json['unreadMessageCount']; _time = json['time']; _userId = json['userId']; _timeStamp = json['TimeStamp']; _status = json['status']; _username = json['username']; } String? _imagePath; String? _lastMessage; bool? _typing; String? _connectedStatus; int? _unreadMessageCount; String? _time; int? _userId; int? _timeStamp; String? _status; String? _username; set imagePath(String? value) { _imagePath = value; } String? get imagePath => _imagePath; String? get lastMessage => _lastMessage; bool? get typing => _typing; String? get connectedStatus => _connectedStatus; int? get unreadMessageCount => _unreadMessageCount; String? get time => _time; int? get userId => _userId; int? get timeStamp => _timeStamp; String? get status => _status; String? get username => _username; Map<String, dynamic> toJson() { final map = <String, dynamic>{}; map['imagePath'] = _imagePath; map['lastMessage'] = _lastMessage; map['typing'] = _typing; map['connectedStatus'] = _connectedStatus; map['unreadMessageCount'] = _unreadMessageCount; map['time'] = _time; map['userId'] = _userId; map['TimeStamp'] = _timeStamp; map['status'] = _status; map['username'] = _username; return map; } set lastMessage(String? value) { _lastMessage = value; } set typing(bool? value) { _typing = value; } set connectedStatus(String? value) { _connectedStatus = value; } set unreadMessageCount(int? value) { _unreadMessageCount = value; } set time(String? value) { _time = value; } set userId(int? value) { _userId = value; } set timeStamp(int? value) { _timeStamp = value; } set status(String? value) { _status = value; } set username(String? value) { _username = value; } }
Flutter获取数据的代码
void getInfo(int? mOtherUserId) async { mUserId = await SecureStorageRepo().getUserProfileId(); debugPrint('mUser info: $mUserId'); debugPrint('mOtherUserId info: $mOtherUserId'); final DatabaseReference mRef = fDatabase .ref(ChatDatabase.connectedUsers) .child('$mUserId') .child('$mOtherUserId'); mRef.once().then((snapshot) { try { var userData = snapshot.snapshot.value; debugPrint('User Snapshot: $userData'); var userDataObject = json.encode(userData); debugPrint('User Snapshot2: $userDataObject'); // 以下代码无法运行 UserDataModel result = UserDataModel.fromJson(userDataObject); debugPrint('Other Users result: ${result.toJson()}'); } catch (e) { debugPrint('User Data Error: ${e.toString()}'); } }); }
问题原因与解决方法
问题根源
Firebase Realtime Database返回的snapshot.snapshot.value本身就是Map<String, dynamic>类型的对象,不需要再调用json.encode(userData)转为JSON字符串。而UserDataModel.fromJson方法接收的是动态Map对象,当传入字符串时,方法内部执行json['imagePath']会把字符串当成数组用索引访问(字符串索引只能是int类型),因此抛出类型不匹配异常。
解决步骤
直接移除多余的json.encode步骤,将原始的snapshot.value传入UserDataModel.fromJson,同时增加非空判断避免空指针异常:
修改后的getInfo方法代码:
void getInfo(int? mOtherUserId) async { mUserId = await SecureStorageRepo().getUserProfileId(); debugPrint('mUser info: $mUserId'); debugPrint('mOtherUserId info: $mOtherUserId'); final DatabaseReference mRef = fDatabase .ref(ChatDatabase.connectedUsers) .child('$mUserId') .child('$mOtherUserId'); mRef.once().then((snapshot) { try { var userData = snapshot.snapshot.value; debugPrint('User Snapshot: $userData'); // 增加非空判断,直接传入Map对象 if (userData != null && userData is Map<String, dynamic>) { UserDataModel result = UserDataModel.fromJson(userData); debugPrint('Other Users result: ${result.toJson()}'); } else { debugPrint('User data is null or invalid format'); } } catch (e) { debugPrint('User Data Error: ${e.toString()}'); } }); }
额外说明
如果需要将模型转为JSON字符串用于存储等场景,可以使用你定义的mUserIdToJson(result)方法,不要和解析流程混淆。
内容的提问来源于stack exchange,提问作者Abhishek VD
相关产品推荐
相关产品推荐

