Flutter/Dart解析API响应时处理空值以避免类型不匹配错误的正确方法
Flutter/Dart解析API响应时处理空值以避免类型不匹配错误的正确方法
看起来你遇到了Dart空安全最典型的坑之一——API返回的null值和你模型里定义的非空类型撞车了。别慌,咱们一步步把这个问题解决掉,以后再遇到类似情况就得心应手了。
核心问题分析
你的API里有些字段(比如match_day、scheduled_at、ended_at)会返回null,但如果你的模型类里把这些字段定义成非空类型(比如int matchDay而不是int? matchDay),Dart的空安全机制就会直接抛出类型不匹配的错误,这就是你现在看到的TypeError: null: type 'Null' is not a subtype of type 'String'的原因。
解决方案分三步走
1. 给模型类的可空字段正确标记可空类型
首先,你要把API可能返回null的字段全部标记为可空类型(在类型后面加?)。结合你的API响应,我帮你修正了Match模型类,你可以参考:
import 'package:wasco_games_mobile_app_v1/models/organization.dart'; import 'package:wasco_games_mobile_app_v1/models/tournament.dart'; class Match { final int id; final String? matchCode; final Team homeTeam; final Team awayTeam; final int homeScore; final int awayScore; final String status; final String? sportCategory; final String? venue; final String? round; final int? matchDay; // API返回null,标记为可空 final Tournament tournament; final DateTime? scheduledAt; // API返回null,标记为可空 final DateTime? startedAt; final DateTime? endedAt; // API返回null,标记为可空 final LiveScore? liveData; Match({ required this.id, this.matchCode, required this.homeTeam, required this.awayTeam, required this.homeScore, required this.awayScore, required this.status, this.sportCategory, this.venue, this.round, this.matchDay, required this.tournament, this.scheduledAt, this.startedAt, this.endedAt, this.liveData, }); // 关键:实现安全的fromJson解析方法 factory Match.fromJson(Map<String, dynamic> json) { return Match( id: json['id'] as int, matchCode: json['match_code'] as String?, homeTeam: Team.fromJson(json['home_team'] as Map<String, dynamic>), awayTeam: Team.fromJson(json['away_team'] as Map<String, dynamic>), // 处理字符串转int,同时防null(API里home_score是字符串,比如"1") homeScore: int.tryParse(json['home_score'] as String) ?? 0, awayScore: int.tryParse(json['away_score'] as String) ?? 0, status: json['status'] as String, sportCategory: json['sport_category'] as String?, venue: json['venue'] as String?, round: json['round'] as String?, matchDay: json['match_day'] as int?, // 直接接受null tournament: Tournament.fromJson(json['tournament'] as Map<String, dynamic>), // 解析DateTime时先判断是否为null scheduledAt: json['scheduled_at'] != null ? DateTime.parse(json['scheduled_at'] as String) : null, startedAt: json['started_at'] != null ? DateTime.parse(json['started_at'] as String) : null, endedAt: json['ended_at'] != null ? DateTime.parse(json['ended_at'] as String) : null, liveData: json['live_data'] != null ? LiveScore.fromJson(json['live_data'] as Map<String, dynamic>) : null, ); } } // 配套的Team模型示例(也要处理可空字段) class Team { final int id; final String name; final String shortName; final Organization organization; Team({ required this.id, required this.name, required this.shortName, required this.organization, }); factory Team.fromJson(Map<String, dynamic> json) { return Team( id: json['id'] as int, name: json['name'] as String, shortName: json['short_name'] as String, organization: Organization.fromJson(json['organization'] as Map<String, dynamic>), ); } } // LiveScore模型示例 class LiveScore { final String elapsedTime; final String matchStatus; final Map<String, String> currentScore; final DateTime lastUpdated; LiveScore({ required this.elapsedTime, required this.matchStatus, required this.currentScore, required this.lastUpdated, }); factory LiveScore.fromJson(Map<String, dynamic> json) { return LiveScore( elapsedTime: json['elapsed_time'] as String, matchStatus: json['match_status'] as String, currentScore: Map<String, String>.from(json['current_score'] as Map), lastUpdated: DateTime.parse(json['last_updated'] as String), ); } }
2. 解析时用默认值替代null(可选,根据业务需求)
如果你不想在UI层处理可空值,可以在解析阶段就给null字段设置默认值。比如:
matchDay: json['match_day'] as int? ?? 0// 把null替换成0venue: json['venue'] as String? ?? '未指定'// 把null替换成默认文本- 注意:DateTime类型不能随便给默认值,除非你有合理的业务逻辑(比如用当前时间替代,但通常不建议),所以还是保持可空更稳妥。
3. UI层安全处理可空值
在UI展示的时候,一定要避免直接使用可空字段,否则还是会报错。你可以用??操作符给null设置替代文本:
// 示例:显示matchDay Text(match.matchDay?.toString() ?? '无轮次'), // 示例:显示scheduledAt Text(match.scheduledAt?.toLocal().toString() ?? '未安排时间'),
额外的小建议
- 尽量不要在代码里用
!强制非空(比如你的service里的response.data!),除非你100%确定这个值不可能为null。虽然你已经判断了response.data != null,但如果API逻辑变了,这个!就会变成隐患。 - 可以考虑用
json_serializable包来自动生成fromJson/toJson方法,它会帮你自动处理空安全,减少手动写代码的错误。
内容来源于stack exchange
相关产品推荐
相关产品推荐

