Flutter结合Retrofit与Dio请求接口报类型不匹配DioError
排查结论与修复方案
触发报错的核心原因
Expected a value of type 'List<dynamic>?', but got one of type 'String'的本质是Retrofit层已经按照接口签名约定,期望拿到Dio解析完成的List<ProductMoel>结构,但实际拿到的是未经JSON解码的字符串原文。
代码中存在的具体问题
- 存在重复的同名
Items类定义:两个类字段配置不一致(一个包含price字段,一个注释移除了price),build_runner生成序列化代码时会产生冲突,无法正确映射JSON字段。 - 模型字段与接口返回结构不匹配:外层分类对象包含
cat_id字段,ProductMoel未对应声明该字段,属于潜在的序列化风险点。 - Dio配置缺失导致响应类型判断错误:
- GitHub raw 资源返回的
Content-Type头是text/plain; charset=utf-8,Dio不会自动将其识别为JSON格式,默认把响应内容作为String类型返回,不会主动解码成List/Map结构。 - 仅手动设置
contentType: "application/json"无法改变Dio对响应类型的判断逻辑,缺少显式的响应解析配置。
- GitHub raw 资源返回的
分步修复操作
- 清理重复类定义,补全模型字段
仅保留和接口字段完全匹配的版本,补充缺失的cat_id字段,最终模型类定义参考:@JsonSerializable() class ProductMoel { @JsonKey(name: 'cat_id') String catId; String categoryName; @JsonKey(name: 'item') List<Items> item; ProductMoel(this.catId, this.categoryName, this.item); factory ProductMoel.fromJson(Map<String, dynamic> json) => _$ProductMoelFromJson(json); Map<String, dynamic> toJson() => _$ProductMoelToJson(this); } @JsonSerializable() class Items { String itemId; String name; int price; Items(this.itemId, this.name, this.price); factory Items.fromJson(Map<String, dynamic> json) => _$ItemsFromJson(json); Map<String, dynamic> toJson() => _$ItemsToJson(this); } - 调整Dio配置,适配非JSON头的响应解析
修改Dio初始化逻辑,强制将纯文本格式的响应自动解码为JSON结构:final dio = Dio(BaseOptions( contentType: "application/json", // 先把响应作为纯文本接收,避免Dio因Content-Type不匹配提前抛错 responseType: ResponseType.plain, )); // 替换默认JSON解码逻辑,对纯文本响应执行JSON解析 dio.transformer = BackgroundTransformer() ..jsonDecodeCallback = (responseStr) => jsonDecode(responseStr); - 重新生成序列化代码
执行命令清理旧生成文件并重新构建:flutter pub run build_runner build --delete-conflicting-outputs
内容的提问来源于stack exchange,提问作者Enamul Haque
相关产品推荐
相关产品推荐

