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

Flutter报错:'String'不是'Map<String, dynamic>'子类型,求代码修复方案

修复API调用异常:'String'类型不是'Map<String, dynamic>'的子类型

问题描述

调用API时触发异常:'String'类型不是'Map<String, dynamic>'的子类型,涉及的MeterDataModel代码如下:

class MeterDataModel {
  int idUnit;
  double startMeter;
  int idUtilities;
  double endMeter;
  String fotoMeter;
  bool flagId;
  DateTime createdDate;
  DateTime periode;
  int createdUser;

  MeterDataModel({
    required this.idUnit,
    required this.startMeter,
    required this.idUtilities,
    required this.endMeter,
    required this.fotoMeter,
    required this.flagId,
    required this.createdDate,
    required this.periode,
    required this.createdUser,
  });

  factory MeterDataModel.fromJson(Map<String, dynamic> json) => MeterDataModel(
        idUnit:int.parse(json["id_unit"]) ,
        startMeter: double.parse(json["start_meter"]),
        idUtilities: json["id_utilities"],
        endMeter: double.parse(json["end_meter"]),
        fotoMeter: json["foto_meter"],
        flagId: json["flag_id"],
        createdDate: DateTime.parse(json["created_date"]),
        periode: DateTime.parse(json["periode"]),
        createdUser: int.parse(json["created_user"]) ,
      );

  Map<String, dynamic> toJson() => {
        "id_unit": idUnit,
        "start_meter": startMeter,
        "id_utilities": idUtilities,
        "end_meter": endMeter,
        "foto_meter": fotoMeter,
        "flag_id": flagId,
        "created_date": createdDate.toIso8601String(),
        "periode":
            "${periode.year.toString().padLeft(4, '0')}-${periode.month.toString().padLeft(2, '0')}-${periode.day.toString().padLeft(2, '0')}",
        "created_user": createdUser,
      };
}

结合截图信息:API返回为包裹结构(包含status、message、data字段),实际仪表数据在data节点下;部分字段返回类型为字符串(如id_unit是字符串而非数字)。

修复步骤

1. 修正API响应解析逻辑

先将API返回的JSON字符串解析为Map,再传入模型fromJson方法,且需取到正确的数据节点:

import 'dart:convert';
import 'package:http/http.dart' as http;

// 示例:处理API响应
final response = await http.get(Uri.parse("你的API地址"));
if (response.statusCode == 200) {
  final jsonResponse = jsonDecode(response.body);
  // 从包裹结构中取出实际数据节点
  final meterDataJson = jsonResponse["data"];
  // 传入模型解析
  final meterData = MeterDataModel.fromJson(meterDataJson);
}

若API返回数据列表,需遍历处理:

final List<dynamic> dataList = jsonResponse["data"];
final List<MeterDataModel> meterList = dataList
    .map((item) => MeterDataModel.fromJson(item))
    .toList();

2. 增强模型类的类型转换健壮性

原模型直接使用int.parse、double.parse存在转换失败风险,修改fromJson方法增加容错处理:

factory MeterDataModel.fromJson(Map<String, dynamic> json) => MeterDataModel(
      idUnit: int.tryParse(json["id_unit"].toString()) ?? 0,
      startMeter: double.tryParse(json["start_meter"].toString()) ?? 0.0,
      idUtilities: int.tryParse(json["id_utilities"].toString()) ?? 0,
      endMeter: double.tryParse(json["end_meter"].toString()) ?? 0.0,
      fotoMeter: json["foto_meter"]?.toString() ?? "",
      flagId: json["flag_id"] is bool ? json["flag_id"] : (json["flag_id"] == "1"),
      createdDate: DateTime.tryParse(json["created_date"].toString()) ?? DateTime.now(),
      periode: DateTime.tryParse(json["periode"].toString()) ?? DateTime.now(),
      createdUser: int.tryParse(json["created_user"].toString()) ?? 0,
    );
  • 用tryParse替代parse,转换失败时返回默认值
  • 对flag_id增加类型判断,兼容数字/字符串形式的布尔值
  • 对字符串字段增加空值处理,避免空指针异常

3. 验证API返回数据结构

确认API返回的data节点是单个Map对象(而非字符串或数组),若data为字符串,需排查后端接口是否存在数据返回错误。


内容的提问来源于stack exchange,提问作者Fandy Ahmad Irianto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 08:05:18