解析服务器JSON遇‘String非Map<String,dynamic>子类型’错误,硬编码正常
问题描述
尝试从网络源解析JSON对象时遇到错误,已确认应用可从服务器获取数据,但模型设置可能存在问题。
服务器返回的JSON格式
{ "neighborhood": [ { "houdeholdId": 1, "members": [ { "father": "John", "mother": "Marry", "child": "Mark" } ] }, { "householdId": 2, "members": [ { "father": "Joseph", "mother": "Anna", "child": "Lisa" } ] } ] }
该数据来自我用于测试的Postman服务器。
控制器文件代码
class Neighbors { late List<HouseHolds> _neighborhood; List<HouseHolds> get neighborhood=> _neighborhood; Neighbors({required neighborhood}){ this._neighborhood = neighborhood; } Neighbors.fromJson(Map<String, dynamic> json) { if (json['neighborhood'] != null) { _neighborhood= <HouseHolds>[]; json['neighborhood'].forEach((v) { _neighborhood!.add(HouseHolds.fromJson(v)); }); } } }
Android Studio提示错误出在Neighbors.fromJson()函数,以下是我的数据获取与解析代码:
List<dynamic> _houseHolds = []; List<dynamic> get houseHolds =>_houseHolds; Future<void> getHouseHolds()async { // fetch and place data from server Response response = await houseHoldsRepo.getHouseHolds(); // successful fetch if(response.statusCode == 200){ _houseHolds = []; // Unhandled Exception: type 'String' is not a subtype of type 'Map<String, dynamic>' _houseHolds.addAll(Neighbors.fromJson(response.body).neighborhood); update(); // refresh app } }
奇怪的是,当我直接硬编码数据时,解析可以正常进行:
List<dynamic> _houseHolds = []; List<dynamic> get houseHolds =>_houseHolds; Future<void> getVendorList()async { // fetch and place data from server Response response = await houseHoldsRepo.getHouseHolds(); // successful fetch if(response.statusCode == 200){ _houseHolds = []; // this works _houseHolds.addAll(Neighbors.fromJson({ "neighborhood": [ { "houdeholdId": 1, "members": [ { "father": "John", "mother": "Marry", "child": "Mark" } ] }, { "householdId": 2, "members": [ { "father": "Joseph", "mother": "Anna", "child": "Lisa" } ] } ] }).neighborhood); update(); // refresh app } }
请问我该如何正确解析服务器返回的JSON数据?
解决方法
核心问题
你遇到的type 'String' is not a subtype of type 'Map<String, dynamic>'错误,本质是直接把服务器返回的字符串格式JSON传给了需要Map类型的Neighbors.fromJson方法。硬编码时传入的是Dart原生Map对象,所以能正常解析,但网络请求返回的response.body是字符串,必须先转换成Map。
具体修复步骤
- 导入JSON解析包:在代码文件顶部添加dart:convert依赖
import 'dart:convert';
- 修改解析逻辑:将字符串格式的响应体转换成Map后再传入模型类
// 替换原解析代码行 final Map<String, dynamic> jsonData = json.decode(response.body); _houseHolds.addAll(Neighbors.fromJson(jsonData).neighborhood);
额外优化建议
- 修正JSON字段拼写错误:服务器返回的第一个对象字段是
houdeholdId(少了一个s),第二个是householdId,这会导致HouseHolds.fromJson解析第一个对象时无法正确获取ID,建议统一字段名为householdId。 - 简化模型类代码:用Dart构造器语法糖优化
Neighbors类,提升可读性和安全性
class Neighbors { final List<HouseHolds> neighborhood; Neighbors({required this.neighborhood}); factory Neighbors.fromJson(Map<String, dynamic> json) { final List<dynamic> neighborhoodList = json['neighborhood'] ?? []; final List<HouseHolds> households = neighborhoodList .map((item) => HouseHolds.fromJson(item)) .toList(); return Neighbors(neighborhood: households); } }
- 提升类型安全性:将
_houseHolds的类型从List<dynamic>改为List<HouseHolds>,避免后续类型转换隐患
List<HouseHolds> _houseHolds = []; List<HouseHolds> get houseHolds => _houseHolds;
内容的提问来源于stack exchange,提问作者lambduh
相关产品推荐
相关产品推荐

