Flutter调用API时遇Null与String类型不匹配错误求助
问题解决思路
核心问题分析
- API返回格式不匹配:目标API返回的是**数组(List)**而非单个对象(Map),但你的代码直接用
Squadre.fromJson解析整个响应体,导致类型不匹配;同时数组内部分对象的字段存在null值,与你定义的非空String字段冲突,触发Null is not a subtype of String错误。 - 字段非空约束冲突:
Squadre类的所有字段都被声明为非空String,但API返回的部分字段(如squ_2allenatore)可能为null,直接赋值会触发类型转换异常。
修正步骤
1. 调整数据模型与解析逻辑
修改Squadre类,将可能为null的字段设为可空类型,并适配API返回的数组格式:
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; // 改为返回List<Squadre>,适配API数组格式 Future<List<Squadre>> fetchSquadre() async { final response = await http .get(Uri.parse('https://www.bkgchallenge.it/badmin/APIM/getsquadre.php')); if (response.statusCode == 200) { // 先解析为List,再逐个转换为Squadre对象 List<dynamic> jsonList = jsonDecode(response.body); return jsonList.map((json) => Squadre.fromJson(json)).toList(); } else { throw Exception('Non sono riuscito a decodificare le squadre'); } } class Squadre { final String squId; final String squNome; final String squStagione; final String? squ1Allenatore; // 设为可空类型 final String? squ2Allenatore; // 设为可空类型 const Squadre({ required this.squId, required this.squNome, required this.squStagione, this.squ1Allenatore, this.squ2Allenatore, }); factory Squadre.fromJson(Map<String, dynamic> json) { return Squadre( // 为必填字段添加空值兜底,避免null赋值给非空String squId: json['squ_id'] ?? '', squNome: json['squ_nome'] ?? '', squStagione: json['squ_stagione'] ?? '', // 可空字段直接接收null squ1Allenatore: json['squ_1allenatore'], squ2Allenatore: json['squ_2allenatore'], ); } }
2. 更新UI展示逻辑
因为返回的是列表数据,改用ListView.builder展示所有球队信息,并处理可空字段的显示:
void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( home: QuoteList(), ); } } class QuoteList extends StatefulWidget { const QuoteList({super.key}); @override State<QuoteList> createState() => _QuoteListState(); } class _QuoteListState extends State<QuoteList> { late Future<List<Squadre>> futureSquadre; @override void initState() { super.initState(); futureSquadre = fetchSquadre(); } @override Widget build(BuildContext context) { return MaterialApp( title: 'Fetch Data Example', theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar( title: const Text('Lista'), ), body: Center( child: FutureBuilder<List<Squadre>>( future: futureSquadre, builder: (context, snapshot) { if (snapshot.hasData) { return ListView.builder( itemCount: snapshot.data!.length, itemBuilder: (context, index) { final squadra = snapshot.data![index]; return ListTile( title: Text(squadra.squNome), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('ID: ${squadra.squId}'), Text('Stagione: ${squadra.squStagione}'), // 对可空字段做null判断,显示兜底文本 Text('Allenatore 1: ${squadra.squ1Allenatore ?? 'Nessuno'}'), Text('Allenatore 2: ${squadra.squ2Allenatore ?? 'Nessuno'}'), ], ), ); }, ); } else if (snapshot.hasError) { return Text('${snapshot.error}'); } // 默认显示加载指示器 return const CircularProgressIndicator(); }, ), ), ), ); } }
关键说明
- 数组解析适配:API返回的是多个球队数据的数组,必须先解析为
List<dynamic>,再遍历转换为Squadre对象,不能直接用单个对象的解析方法。 - 空值安全处理:对于API可能返回null的字段,要么声明为可空类型,要么用
??运算符设置兜底值(如空白字符串),避免类型转换异常。 - UI适配列表数据:用
ListView.builder展示列表数据,同时对可空字段做null判断,保证UI渲染时不会因null值报错。
内容的提问来源于stack exchange,提问作者Mauro Ds
相关产品推荐
相关产品推荐

