Dart列表去重分组及运算符[]未定义错误解决求助
Dart数据分组转换问题及解决
原始数据
我有如下Dart Map列表数据:
[ { "ExtendedDutyId":1, "DutyName":"Overtime duties", "DutyDate":"2022-10-26", "FromTime":"0:00", "ToTime":"36:00", "Allowance":0, "ShiftType":-1, "ShiftCode":-1, "Employee":{ "EmployeeId":1025, "FirstName":"Daniel", "LastName":"Hansen-Hansen", "CompanyCode":"BY" } }, { "ExtendedDutyId":1, "DutyName":"Overtime duties", "DutyDate":"2022-10-26", "FromTime":"5:11", "ToTime":"10:29", "Allowance":0, "ShiftType":-1, "ShiftCode":1314679, "Employee":{ "EmployeeId":1025, "FirstName":"Daniel", "LastName":"Hansen-Hansen", "CompanyCode":"BY" } }, { "ExtendedDutyId":1, "DutyName":"Overtime duties", "DutyDate":"2022-10-27", "FromTime":"0:00", "ToTime":"36:00", "Allowance":0, "ShiftType": -1, "ShiftCode":-1, "Employee":{ "EmployeeId":1025, "FirstName":"Daniel", "LastName":"Hansen-Hansen", "CompanyCode":"BY" } } ]
目标结构
希望将上述数据处理后得到如下结构(注:原描述中“按DateOfBirth分组”应为笔误,实际为按员工分组并转换时间格式):
{ "employeeTimeRegStatus":[ { "supervisor":1035, "employeeId":1025, "companyCode":"BY", "statusId":1, "timeRegs":[ { "ExtendedDutyId":1, "DutyName":"Overtime duties", "DutyDate":"2022-10-26", "FromTime":0, "ToTime":2160, "ShiftType":-1, "ShiftCode":-1, "Allowance":0 }, { "ExtendedDutyId":1, "DutyName":"Overtime duties", "DutyDate":"2022-10-27", "FromTime":0, "ToTime":2160, "ShiftType":-1, "ShiftCode":-1, "Allowance":0 }, { "ExtendedDutyId":1, "DutyName":"Overtime duties", "DutyDate":"2022-10-26", "FromTime":311, "ToTime":629, "ShiftType":-1, "ShiftCode":1314679, "Allowance":0 } ] } ] }
遇到的错误
尝试代码时出现如下错误:
The operator '[]' isn't defined for the class 'Object?'
尝试的代码
final value = xdata.fold(Map<String, List<dynamic>>(), (Map<String, List<dynamic>> a, b) { a.putIfAbsent(b["Employee"]!["FirstName"].toString(), () => []).add(b); return a; }).values .where((l) => l.isNotEmpty) .map((l) => { 'Supervisor': l.first["Supervisor"], 'employeeId': l.first["employeeId"], 'companyCode': l.first["companyCode"], 'statusId': l.first["statusId"], 'TimeRegs': l.map((e) => { 'ExtendedDutyId': e['ExtendedDutyId'], 'DutyName': e['DutyName'], 'DutyDate': e['DutyDate'], 'FromTime': e['FromTime'], 'ToTime': e['ToTime'], 'ShiftType': e['ShiftType'], 'ShiftCode': e['ShiftCode'], 'Allowance': e['Allowance'], }).toList() }).toList();
相关模型类
class EmployeeTimeRegStatus { int? supervisor; int? employeeId; String? companyCode; int? statusId; List<TimeRegs>? timeRegs; EmployeeTimeRegStatus( {this.supervisor, this.employeeId, this.companyCode, this.statusId, this.timeRegs});}
问题分析与解决
错误原因
- 类型推断问题:
b["Employee"]返回Object?类型,直接使用[]操作符会触发类型错误,需明确转换为Map类型。 - 字段匹配错误:原始数据中没有
Supervisor、employeeId、companyCode、statusId这些顶层字段,需从Employee子Map中获取对应字段,statusId和supervisor为固定值。 - 时间格式未转换:目标结构要求将
FromTime/ToTime的字符串格式转换为分钟数,原代码未处理该逻辑。
修正后的代码
首先补充TimeRegs模型类:
class TimeRegs { int? extendedDutyId; String? dutyName; String? dutyDate; int? fromTime; int? toTime; int? shiftType; int? shiftCode; int? allowance; TimeRegs({ this.extendedDutyId, this.dutyName, this.dutyDate, this.fromTime, this.toTime, this.shiftType, this.shiftCode, this.allowance, }); }
然后是数据处理核心代码:
// 辅助函数:将"小时:分钟"格式字符串转换为总分钟数 int convertTimeToMinutes(String timeStr) { final parts = timeStr.split(':'); if (parts.length != 2) return 0; final hours = int.tryParse(parts[0]) ?? 0; final minutes = int.tryParse(parts[1]) ?? 0; return hours * 60 + minutes; } // 处理数据并转换为目标模型 List<EmployeeTimeRegStatus> processData(List<Map<String, dynamic>> xdata) { // 按员工ID分组(比姓名更可靠,避免重名) final groupedData = <int, List<Map<String, dynamic>>>{}; for (final item in xdata) { final employee = item["Employee"] as Map<String, dynamic>; final employeeId = employee["EmployeeId"] as int; groupedData.putIfAbsent(employeeId, () => []).add(item); } // 转换为目标模型列表 return groupedData.entries.map((entry) { final employeeId = entry.key; final items = entry.value; final firstEmployee = items.first["Employee"] as Map<String, dynamic>; final companyCode = firstEmployee["CompanyCode"] as String; // 转换timeRegs列表 final timeRegs = items.map((item) { return TimeRegs( extendedDutyId: item["ExtendedDutyId"] as int, dutyName: item["DutyName"] as String, dutyDate: item["DutyDate"] as String, fromTime: convertTimeToMinutes(item["FromTime"] as String), toTime: convertTimeToMinutes(item["ToTime"] as String), shiftType: item["ShiftType"] as int, shiftCode: item["ShiftCode"] as int, allowance: item["Allowance"] as int, ); }).toList(); return EmployeeTimeRegStatus( supervisor: 1035, // 固定值,可根据业务逻辑调整来源 employeeId: employeeId, companyCode: companyCode, statusId: 1, // 固定值,可根据业务逻辑调整来源 timeRegs: timeRegs, ); }).toList(); } // 使用示例 // final processedList = processData(yourOriginalDataList);
代码说明
- 明确类型转换:将
item["Employee"]强制转换为Map<String, dynamic>,解决Object?类型无法使用[]的问题。 - 可靠分组逻辑:改用员工ID作为分组键,避免姓名重复导致的分组错误。
- 时间格式转换:通过辅助函数将时间字符串转换为分钟数,匹配目标结构要求。
- 类型安全映射:直接映射到定义好的模型类,避免动态Map的类型风险。
内容的提问来源于stack exchange,提问作者Arslan
相关产品推荐
相关产品推荐

