Flutter中展示JSON嵌套对象(Map)及解决'Null'与'Map<dynamic, dynamic>'类型不兼容错误
解决Flutter中JSON解析的
Null类型不匹配问题 你遇到的type 'Null' is not a subtype of type 'Map<dynamic, dynamic>'错误,本质是API返回的JSON中某个字段为null,但你的实体类stations里定义的是不可为空的Map类型,导致解析时类型不兼容。下面一步步帮你解决:
1. 定位问题根源
先确认你的API返回JSON结构,比如是否存在nom、comp等字段为null的情况。举个例子,如果返回的JSON像这样:
{ "ond": {}, "comp": null, "gaz": {}, "eau": {}, "nom": {"station1": "Station A", "station2": "Station B"} }
这里comp字段是null,而你的实体类里comp是final Map(必须非空),就会触发这个错误。
2. 修改实体类处理null字段
有两种常见的解决方式,选适合你的:
方式一:允许字段为null
把实体类里的Map改成可空的Map?,这样即使API返回null也不会报错:
class stations { final Map? ond; final Map? comp; final Map? gaz; final Map? eau; final Map? nom; const stations({ this.ond, this.comp, this.eau, this.gaz, this.nom, }); factory stations.fromJson(Map<String, dynamic> json) { return stations( ond: json['ond'] as Map?, comp: json['comp'] as Map?, eau: json['eau'] as Map?, gaz: json['gaz'] as Map?, nom: json['nom'] as Map?, ); } }
之后使用的时候记得先判断是否为null,比如:
if (snapshot.data!.nom != null) { // 处理nom字段的逻辑 }
方式二:给null字段设置默认空Map
如果希望字段始终是Map类型(非空),可以在解析时把null替换成空Map:
class stations { final Map ond; final Map comp; final Map gaz; final Map eau; final Map nom; const stations({ required this.ond, required this.comp, required this.eau, required this.gaz, required this.nom, }); factory stations.fromJson(Map<String, dynamic> json) { return stations( ond: json['ond'] as Map? ?? {}, comp: json['comp'] as Map? ?? {}, eau: json['eau'] as Map? ?? {}, gaz: json['gaz'] as Map? ?? {}, nom: json['nom'] as Map? ?? {}, ); } }
这样不管API返回null还是正常的Map,你的实体类字段都会是有效的Map,避免类型错误。
3. 后续创建TabBar的示例
假设你的nom字段是Map<String, String>格式(键是标识,值是Tab标题),可以这样生成TabBar:
if (snapshot.hasData) { // 从nom字段提取所有标题 final tabTitles = snapshot.data!.nom.values.toList(); return DefaultTabController( length: tabTitles.length, child: Scaffold( appBar: AppBar( bottom: TabBar( tabs: tabTitles.map((title) => Tab(text: title)).toList(), ), ), body: TabBarView( children: tabTitles.map((title) { return Center(child: Text('内容:$title')); }).toList(), ), ), ); }
小优化:简化Build方法
你当前的Build方法里,创建Center后没使用,直接返回f1,可以简化成这样:
@override Widget build(BuildContext context) { print('builder'); return FutureBuilder<stations>( future: futureDonnee, builder: (context, snapshot) { if (snapshot.hasData) { // 这里放上面的TabBar逻辑或者你的原有UI } else if (snapshot.hasError) { return Text('${snapshot.error}'); } return const CircularProgressIndicator(); }, ); }
内容的提问来源于stack exchange,提问作者rooroo
相关产品推荐
相关产品推荐

