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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 20:22:26