Flutter报错Null不是String子类型 汇率API数据解析问题求解
问题根因
你遇到的type 'Null' is not a subtype of type 'String'错误,是因为你声明Album类的msg字段为不可空的String类型,但解析JSON时直接从根节点取json['msg']返回了null,Dart无法完成类型转换触发报错。https://api.exchangerate.host/latest接口返回的msg字段不是根级字段,而是嵌套在motd对象下,同时你要的汇率数据在根级的rates字段中,接口返回结构示例如下:
{ "motd": { "msg": "If you or your company use this project or like what we doing, please consider backing us so we can continue maintaining and evolving this project.", "url": "..." }, "base": "EUR", "date": "2024-xx-xx", "rates": { "AED": 3.6725, "AFN": 91.80, // 其余货币汇率 } }
修复方案
1. 修正Album类的解析逻辑
调整字段取值路径,同时新增rates字段存储汇率数据,可选增加空安全处理避免接口结构变化时再次崩溃:
class Album { final String msg; final Map<String, dynamic> rates; Album({ required this.msg, required this.rates, }); factory Album.fromJson(Map<String, dynamic> json) { return Album( // 从motd对象下取msg,空值时返回默认提示 msg: json['motd']?['msg'] ?? '暂无提示信息', // 取根节点下的rates字段,空值时返回空Map rates: json['rates'] ?? <String, dynamic>{}, ); } }
2. 调整页面展示逻辑
修改FutureBuilder的布局,同时展示提示信息和汇率列表:
@override Widget build(BuildContext context) { return MaterialApp( title: 'Fetch Data Example', theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar( title: const Text('Fetch Data Example'), ), body: Center( child: FutureBuilder<Album>( future: futureAlbum, builder: (context, snapshot) { if (snapshot.hasData) { return Column( children: [ // 展示接口提示信息 Padding( padding: const EdgeInsets.all(16.0), child: Text(snapshot.data!.msg), ), // 展示货币汇率列表 Expanded( child: ListView.builder( itemCount: snapshot.data!.rates.length, itemBuilder: (context, index) { String currencyCode = snapshot.data!.rates.keys.elementAt(index); num exchangeRate = snapshot.data!.rates.values.elementAt(index); return ListTile( title: Text('$currencyCode: $exchangeRate'), ); }, ) ) ], ); } else if (snapshot.hasError) { return Text('${snapshot.error}'); } return const CircularProgressIndicator(); }, ), ), ), ); }
内容的提问来源于stack exchange,提问作者Lakshan Costa
相关产品推荐
相关产品推荐

