Dart自定义对象JSON序列化与反序列化问题求助
问题排查与修复
核心问题1:LateBus的JSON键名大小写不匹配
LateBus的fromJson构造函数中使用大写开头的键名(如'AppliesTo'、'RouteRun'),但toJson方法输出的是小写开头的键名(如'appliesTo'、'routeRun')。这种不一致会导致反序列化时无法正确映射字段,出现字段为空或类型转换异常。
核心问题2:lateBuses的序列化方式错误
School类对lateBuses的处理冗余且逻辑错误:
toJson里用jsonEncode(lateBuses)把列表转成JSON字符串,导致整个School对象序列化后,lateBuses字段是字符串而非数组格式。- 反序列化时又用
jsonDecode(json['lateBuses'])解析,这种双重编码/解码不仅完全没必要,还会引发格式错误(比如整个School列表被jsonEncode时,内部的JSON字符串会被再次转义,最终解码失败)。
修正后的代码
School类修正:
class School implements Comparable<School> { final String name; final List<String> aliases; bool isFavorite; List<LateBus> lateBuses; // 其他构造函数... School.fromJson(Map<String, dynamic> json) : name = json['name'] as String, aliases = List<String>.from(json['aliases']), isFavorite = json['isFavorite'] as bool, // 直接将列表中的Map转成LateBus,无需额外jsonDecode lateBuses = (json['lateBuses'] as List) .map((e) => LateBus.fromJson(e as Map<String, dynamic>)) .toList(); Map<String, dynamic> toJson() => { 'name': name, 'aliases': aliases, 'isFavorite': isFavorite, // 直接返回LateBus列表,由顶层jsonEncode自动处理序列化 'lateBuses': lateBuses.map((bus) => bus.toJson()).toList(), }; @override int compareTo(School other) => name.compareTo(other.name); }
LateBus类修正:
class LateBus { String appliesTo; String routeRun; dynamic zone; // 替换as Null,用dynamic或String?更符合Dart规范 String operator; String action; String affectsSchools; String transfersSchools; String comment; bool isCreateTimeVisible; String createTime; String createTimeDisplay; // 其他构造函数... LateBus.fromJson(Map<String, dynamic> json) // 统一使用与toJson一致的小写键名 : appliesTo = json['appliesTo'] as String, routeRun = json['routeRun'] as String, zone = json['zone'], operator = json['operator'] as String, action = json['action'] as String, affectsSchools = json['affectsSchools'] as String, transfersSchools = json['transfersSchools'] as String, comment = json['comment'] as String, isCreateTimeVisible = json['isCreateTimeVisible'] as bool, createTime = json['createTime'] as String, createTimeDisplay = json['createTimeDisplay'] as String; Map<String, dynamic> toJson() => { 'appliesTo': appliesTo, 'routeRun': routeRun, 'zone': zone, 'operator': operator, 'action': action, 'affectsSchools': affectsSchools, 'transfersSchools': transfersSchools, 'comment': comment, 'isCreateTimeVisible': isCreateTimeVisible, 'createTime': createTime, 'createTimeDisplay': createTimeDisplay, }; }
额外提示
- 保存到SharedPreferences时,直接对School列表做顶层
jsonEncode:final schools = <School>[...]; await SharedPreferences.getInstance().then((prefs) { prefs.setString('schools', jsonEncode(schools)); }); - 加载时做顶层
jsonDecode:final prefs = await SharedPreferences.getInstance(); final jsonString = prefs.getString('schools'); if (jsonString != null) { final List<dynamic> jsonList = jsonDecode(jsonString); final schools = jsonList.map((e) => School.fromJson(e as Map<String, dynamic>)).toList(); }
内容的提问来源于stack exchange,提问作者Joseph Lam
相关产品推荐
相关产品推荐

