Flutter从API获取数据后报错:期望String类型却得到TypeErrorImpl
Flutter JSON解析类型错误修复:Expected a value of type 'String', but got one of type 'TypeErrorImpl'
问题现象
请求API成功获取部门JSON响应,但处理响应时抛出错误:
Uncaught (in promise) Error: Expected a value of type 'String', but got one of type 'TypeErrorImpl'
API返回的JSON响应
{ "success": true, "data": [ { "id": "56c8b5f8-7f74-4f0c-9fc0-9a3c411bc3a4", "image": "http://127.0.0.1:8000/media/api/uploads/departments/2023/03/14/child_yk4u2KO.png", "name": "Education And Child Development", "slug": "education-and-child-development", "created_at": "2023-02-23T14:51:39Z", "updated_at": "2023-03-14T14:24:10.699998Z" } ], "message": "Departments successfuly retrieved" }
问题代码分析
Department实体类(department.dart)
class Department { String id; String image; String name; String slug; Department({ this.id, this.image, this.name, this.slug, }); Department.fromJson(Map<String, dynamic> json) { id = json['id'].toString(); image = json['image'] != null ? json['image'] : null; name = json['name'] != null ? json['name'] : null; slug = json['slug']; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = new Map<String, dynamic>(); data['id'] = this.id; data['image'] = this.image; data['name'] = this.name; data['slug'] = this.slug; return data; } }
数据获取函数
Future<Stream<Department>> getSchoolDepartments() async { final String url = '${GlobalConfiguration().getString('api_base_url')}departments'; final client = new http.Client(); try { final streamedRest = await client.send(http.Request('get', Uri.parse(url))); print("Status code : " + streamedRest.statusCode.toString()); return streamedRest.stream .transform(utf8.decoder) .transform(json.decoder) .map((data) => Helper.getData(data)) .expand((data) => (data as List)) .map((data) { print("data : " + data); // 错误根源:data是Map类型,无法直接与字符串拼接 return Department.fromJson(data); }); } on Exception catch (e) { print(e); } }
数据处理函数(school_controller.dart)
void listenForDepartments() async { print("starting departments stream"); final Stream<Department> stream = await getSchoolDepartments(); stream.listen((Department _department) { setState(() => departments.add(_department)); }, onError: (a) { print("Failed to add department : " + a); // 错误:a是Error类型,不能直接拼接字符串 }, onDone: () {}); }
错误根源
- 数据获取函数的print语句:
print("data : " + data);中的data是Map<String, dynamic>类型,直接与字符串用+拼接触发类型不匹配错误,这是抛出TypeErrorImpl的直接原因。 - 错误处理的字符串拼接:
onError回调里的print("Failed to add department : " + a);,a是Error对象,无法直接与字符串拼接。
修复方案
1. 修正数据获取函数的print语句
将Map类型的data转为字符串后再打印:
.map((data) { print("data : ${data.toString()}"); // 用字符串插值转换为String return Department.fromJson(data); });
2. 修正错误处理中的字符串拼接
用字符串插值自动转换Error对象为字符串:
onError: (a) { print("Failed to add department : $a"); },
3. 可选:优化实体类空安全处理(适配Flutter空安全版本)
给字段添加空安全修饰符,避免潜在空指针问题:
class Department { String? id; String? image; String? name; String? slug; Department({ this.id, this.image, this.name, this.slug, }); Department.fromJson(Map<String, dynamic> json) { id = json['id']?.toString(); // 空安全访问 image = json['image']; name = json['name']; slug = json['slug']; } // toJson方法保持不变 }
验证修复
运行代码后,API响应的JSON数据会被正确解析为Department对象并添加到departments列表中,不再抛出类型错误。
内容的提问来源于stack exchange,提问作者TEX
相关产品推荐
相关产品推荐

