Flutter中通过API调用嵌套JSON数据及解析报错求助
解决Flutter解析嵌套JSON时的「List无法赋值给String」错误
嘿,我看你在解析嵌套JSON的时候碰到了这个类型错误,这个问题其实挺常见的,大多是因为数据类型在某个环节没对应上,咱们一步步来排查和解决:
先搞清楚错误根源
The argument type 'List' can't be assigned to the parameter type 'String'这个错误,本质是你把一个List类型的数据,传给了需要String类型的参数——大概率是在API解析完成后,UI展示或者数据传递的时候出了问题,咱们先从核心的解析流程和实体类开始检查。
1. 优化你的实体类代码
你的实体类整体逻辑是对的,但有几个小细节可以调整,避免后续踩坑:
- 初始化List的时候,建议用更简洁的
map写法替代forEach,不仅代码更紧凑,还能避免手动初始化List时可能出现的问题:
// 修改Album.fromJson的解析逻辑 Album.fromJson(Map<String, dynamic> json) { info = (json['Info'] as List).map((v) => Info.fromJson(v)).toList(); }
如果坚持用forEach,记得显式声明List为可增长类型:
info = List<Info>.empty(growable: true); json['Info'].forEach((v) { info.add(Info.fromJson(v)); });
2. 检查API请求与解析的完整流程
确保你发起请求后,正确把响应体转成JSON再实例化Album对象,比如正确的请求流程应该是这样的:
Future<Album> fetchCleaningTypes() async { final response = await http.get(Uri.parse('你的API接口地址')); if (response.statusCode == 200) { // 正确解析JSON为Album实体 return Album.fromJson(jsonDecode(response.body)); } else { throw Exception('加载清洁类型失败'); } }
如果你在这里不小心把jsonDecode(response.body)直接当成String用,或者传给了需要String的参数,就会触发错误。
3. 排查UI展示时的错误(最可能的原因)
如果解析流程和实体类都没问题,那错误十有八九出在UI层——比如你可能直接把album.info(一个List<Info>)传给了需要String的Widget,比如Text():
// ❌ 错误示例:把List直接传给Text Text(album.info)
正确的做法是遍历这个List,逐个展示每个Info的内容,比如用ListView:
// ✅ 正确示例:遍历List展示内容 ListView.builder( itemCount: album.info.length, itemBuilder: (context, index) { final cleaningItem = album.info[index]; return ListTile( title: Text(cleaningItem.cleaningType), subtitle: Text('ID: ${cleaningItem.cTypeId}'), ); }, )
完整的可运行示例
这里给你一个包含请求、解析、UI展示的完整代码,你可以直接参考:
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; class Album { List<Info> info; Album({this.info}); Album.fromJson(Map<String, dynamic> json) { info = (json['Info'] as List).map((v) => Info.fromJson(v)).toList(); } Map<String, dynamic> toJson() { final Map<String, dynamic> data = Map<String, dynamic>(); if (info != null) { data['Info'] = info.map((v) => v.toJson()).toList(); } return data; } } class Info { String cTypeId; String cleaningType; Info({this.cTypeId, this.cleaningType}); Info.fromJson(Map<String, dynamic> json) { cTypeId = json['c_type_id']; cleaningType = json['cleaning type']; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = Map<String, dynamic>(); data['c_type_id'] = cTypeId; data['cleaning type'] = cleaningType; return data; } } void main() => runApp(const MyApp()); class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { late Future<Album> futureCleaningTypes; @override void initState() { super.initState(); futureCleaningTypes = fetchCleaningTypes(); } Future<Album> fetchCleaningTypes() async { // 替换成你的真实API地址,或者用模拟数据测试 final response = await http.get(Uri.parse('https://your-api-url.com/cleaning-types')); if (response.statusCode == 200) { return Album.fromJson(jsonDecode(response.body)); } else { throw Exception('加载清洁类型失败,请稍后重试'); } } @override Widget build(BuildContext context) { return MaterialApp( title: '清洁类型列表', theme: ThemeData(primarySwatch: Colors.blue), home: Scaffold( appBar: AppBar(title: const Text('清洁类型')), body: Center( child: FutureBuilder<Album>( future: futureCleaningTypes, builder: (context, snapshot) { if (snapshot.hasData) { return ListView.builder( padding: const EdgeInsets.all(16), itemCount: snapshot.data!.info.length, itemBuilder: (context, index) { final item = snapshot.data!.info[index]; return Card( margin: const EdgeInsets.only(bottom: 12), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(item.cleaningType, style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), const SizedBox(height: 8), Text('类型ID: ${item.cTypeId}'), ], ), ), ); }, ); } else if (snapshot.hasError) { return Text('出错了: ${snapshot.error}'); } // 加载中状态 return const CircularProgressIndicator(); }, ), ), ), ); } }
最后总结一下
你遇到的错误核心就是List类型和String类型的不匹配,优先检查这几个点:
- API解析后是否正确得到了Album对象,而不是直接处理原始的List
- UI层有没有把List直接传给需要String的Widget(比如Text)
- 实体类中List的初始化是否正确
内容的提问来源于stack exchange,提问作者parveen
相关产品推荐
相关产品推荐

