You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 00:07:35