You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中Dio报错:'String'无法转为'Map<String, dynamic>'类型

问题分析与解决方案

错误根源

这个报错type 'String' is not a subtype of type 'Map<String, dynamic>' in type cast说白了就是:你把接口返回的字符串数据硬当成Map格式去解析成SurveyDataModel,类型对不上才炸的。常见情况有这几种:

  • 接口实际返回的是纯文本(比如"请求成功"、错误提示),不是JSON对象
  • 接口返回的JSON格式有问题(比如是数组[]不是单个对象{},或者语法错误)
  • Dio请求时没处理好响应格式(比如手动把数据转成了字符串,或者没设置正确的responseType)

分模块排查修复

1. GetTasksRepo 层:先搞清楚接口返回的是什么

你得先把Dio请求的响应数据打出来看看,别上来就强转类型:

// 错误示范:直接把response.data当Map转
final Map<String, dynamic> data = response.data as Map<String, dynamic>;

// 正确操作:先判断类型,再处理
Future<SurveyDataModel> getSurveyById(String surveyId) async {
  try {
    final response = await dio.get('/surveys/$surveyId');
    
    // 先打印这俩,看看接口到底返回啥
    print('问卷接口返回内容:${response.data}');
    print('返回数据类型:${response.data.runtimeType}');

    if (response.data is Map<String, dynamic>) {
      return SurveyDataModel.fromJson(response.data);
    } else if (response.data is String) {
      // 如果是字符串,先试试能不能转成JSON
      try {
        final jsonData = jsonDecode(response.data) as Map<String, dynamic>;
        return SurveyDataModel.fromJson(jsonData);
      } catch (e) {
        throw Exception('JSON格式错了:$e');
      }
    } else {
      throw Exception('返回类型不对:${response.data.runtimeType}');
    }
  } catch (e) {
    throw Exception('Dio请求出问题:$e');
  }
}
  • 重点:先打印确认返回内容和类型,别瞎猜
  • 如果接口返回的是JSON数组(比如[{"id":1}]),那得把解析逻辑改成处理List<Map<String,dynamic>>,还要对应改Model的解析方法

2. SurveyDataModel 层:Model结构要和接口返回对应上

检查你的fromJson方法,字段和接口返回的JSON key得对上:

// 举个例子,你得根据实际接口返回改
class SurveyDataModel {
  final String id;
  final String title;
  final List<QuestionModel> questions;

  SurveyDataModel({required this.id, required this.title, required this.questions});

  factory SurveyDataModel.fromJson(Map<String, dynamic> json) {
    // 最好给字段加默认值,避免接口返回null炸锅
    return SurveyDataModel(
      id: json['id'] ?? '',
      title: json['title'] ?? '',
      questions: (json['questions'] as List?)?.map((q) => QuestionModel.fromJson(q)).toList() ?? [],
    );
  }
}
  • 要是接口返回的JSON里没有某个key,或者类型和Model字段不匹配,也会触发类型错误
  • 加个??给默认值,能减少不少意外报错

3. SurveyScreen 层:跳转和加载逻辑别出错

跳转的时候要传对问卷ID,页面加载时要捕获错误:

class SurveyScreen extends StatefulWidget {
  final String surveyId;

  const SurveyScreen({super.key, required this.surveyId});

  @override
  State<SurveyScreen> createState() => _SurveyScreenState();
}

class _SurveyScreenState extends State<SurveyScreen> {
  SurveyDataModel? _survey;
  String? _errorMsg;

  @override
  void initState() {
    super.initState();
    _loadSurvey();
  }

  Future<void> _loadSurvey() async {
    try {
      final survey = await GetTasksRepo().getSurveyById(widget.surveyId);
      setState(() {
        _survey = survey;
      });
    } catch (e) {
      setState(() {
        _errorMsg = e.toString();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    if (_errorMsg != null) {
      return Center(child: Text('加载失败:$_errorMsg'));
    }
    if (_survey == null) {
      return const Center(child: CircularProgressIndicator());
    }
    // 渲染问卷内容
    return Scaffold(
      appBar: AppBar(title: Text(_survey!.title)),
      body: ListView(
        children: _survey!.questions.map((q) => Text(q.text)).toList(),
      ),
    );
  }
}
  • 跳转的时候要确保传的ID正确:比如任务列表里点按钮时Navigator.push(context, MaterialPageRoute(builder: (_) => SurveyScreen(surveyId: task.surveyId)));
  • 页面里加错误提示,出问题的时候能直接看到啥原因

额外排查小技巧

  1. 用Postman或者浏览器直接访问问卷接口,看看返回的内容是不是你预期的JSON对象
  2. 检查Dio的全局配置,有没有把responseType改成ResponseType.plain了(默认是JSON,改了就会返回字符串)
  3. 如果返回的是HTML页面(比如404、500错误页),那就是接口地址错了或者后端出问题了,先把接口搞定

内容的提问来源于stack exchange,提问作者KLVN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 14:52:37