【问题标题】:Unhandled Exception: type 'String' is not a subtype of type 'Map<String, dynamic>'未处理的异常:“String”类型不是“Map<String, dynamic>”类型的子类型
【发布时间】:2021-06-11 12:39:02
【问题描述】:

我不确定发生了什么,因为我的代码工作正常,但突然停止工作,我认为我没有改变任何与此相关的内容。我已经坚持了两天,无法弄清楚我做错了什么。 API 返回的数据是正确的,返回状态码为 200

我认为该错误与PTWorkoutPlanItem.fromJson() 函数有关。我认为这与PTWorkoutPlanItem 模型中的List&lt;AssignedUsers&gt;List&lt;WorkoutPlanItem&gt; 模型没有任何关系,因为当我将它们更改为dynamic 时,错误仍然存​​在

错误提示

[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: type 'String' is not a subtype of type 'Map<String, dynamic>'

获取数据的代码:

  getPlanData() async {
    var data = PTWorkoutPlanItem.fromJson(
        await get(url: 'pt/workouts/plan/' + planId.toString()));
  }

// Console logged the response here and it is correct, so this function works
Future<dynamic> get({url}) async {
  final response = await http.get(baseUrl + url, headers: headers);
  print(response.statusCode);

  dynamic res = json.decode(response.body);
  return res;
}

模型

class PTWorkoutPlanItem {
  int id;
  String title;
  List<AssignedUsers> assignedUsers;
  List<WorkoutPlanItem> workouts;
  int ptId;

  PTWorkoutPlanItem(
      {this.id, this.title, this.assignedUsers, this.workouts, this.ptId});

  factory PTWorkoutPlanItem.fromJson(Map<String, dynamic> json) {
    return PTWorkoutPlanItem(
      id: json['id'],
      title: json['title'],
      assignedUsers: List.from(json['assignedUsers'])
          .map((item) => AssignedUsers.fromJson(item))
          .toList(),
      workouts: List.from(json['workouts'])
          .map((item) => WorkoutPlanItem.fromJson(item))
          .toList(),
      ptId: json['ptId'],
    );
  }
}

class AssignedUsers {
  int id;
  String title;

  AssignedUsers({this.id, this.title});

  factory AssignedUsers.fromJson(Map<String, dynamic> json) {
    return AssignedUsers(id: json['id'], title: json['title']);
  }
}

class WorkoutPlanItem {
  int id;
  String title;
  int duration;
  int sets;
  int rest;

  WorkoutPlanItem({this.id, this.title, this.duration, this.sets, this.rest});

  factory WorkoutPlanItem.fromJson(Map<String, dynamic> json) {
    return WorkoutPlanItem(
      id: json['id'],
      title: json['title'],
      duration: json['duration'],
      sets: json['sets'],
      rest: json['rest'],
    );
  }
}

这是在 API 中重新调整的内容

{
    "id": 1,
    "title": "Pull day",
    "assignedUsers": [
        {
            "id": 1,
            "title": "josh"
        },
        {
            "id": 2,
            "title": "marus"
        }
    ],
    "workouts": [
        {
            "id": 4,
            "title": "Workout item 4",
            "duration": 10,
            "sets": 3,
            "rest": 3
        },
        {
            "id": 1,
            "title": "Workout item 1",
            "duration": 10,
            "sets": 3,
            "rest": 3
        }
    ],
    "ptId": 1
}

【问题讨论】:

    标签: json flutter dart


    【解决方案1】:

    试试这个。我添加了很多类型转换,但最重要的部分是我如何处理 List&lt;dynamic&gt; 并将每个元素转换为 Map&lt;String, dynamic&gt;

    class PTWorkoutPlanItem {
      int id;
      String title;
      List<AssignedUsers> assignedUsers;
      List<WorkoutPlanItem> workouts;
      int ptId;
    
      PTWorkoutPlanItem(
          {this.id, this.title, this.assignedUsers, this.workouts, this.ptId});
    
      factory PTWorkoutPlanItem.fromJson(Map<String, dynamic> json) {
        return PTWorkoutPlanItem(
          id: json['id'] as int,
          title: json['title'] as String,
          assignedUsers: (json['assignedUsers'] as List<dynamic>)
              .cast<Map<String, dynamic>>()
              .map((item) => AssignedUsers.fromJson(item))
              .toList(),
          workouts: (json['workouts'] as List<dynamic>)
              .cast<Map<String, dynamic>>()
              .map((item) => WorkoutPlanItem.fromJson(item))
              .toList(),
          ptId: json['ptId'] as int,
        );
      }
    }
    
    class AssignedUsers {
      int id;
      String title;
    
      AssignedUsers({this.id, this.title});
    
      factory AssignedUsers.fromJson(Map<String, dynamic> json) {
        return AssignedUsers(id: json['id'] as int, title: json['title'] as String);
      }
    }
    
    class WorkoutPlanItem {
      int id;
      String title;
      int duration;
      int sets;
      int rest;
    
      WorkoutPlanItem({this.id, this.title, this.duration, this.sets, this.rest});
    
      factory WorkoutPlanItem.fromJson(Map<String, dynamic> json) {
        return WorkoutPlanItem(
          id: json['id'] as int,
          title: json['title'] as String,
          duration: json['duration'] as int,
          sets: json['sets'] as int,
          rest: json['rest'] as int,
        );
      }
    }
    

    另外,这里有一个 Dart 2.12 兼容版本,其中 required 添加到命名参数,因为它们都不允许是 null 并且没有任何默认值:

    class PTWorkoutPlanItem {
      int id;
      String title;
      List<AssignedUsers> assignedUsers;
      List<WorkoutPlanItem> workouts;
      int ptId;
    
      PTWorkoutPlanItem(
          {required this.id,
          required this.title,
          required this.assignedUsers,
          required this.workouts,
          required this.ptId});
    
      factory PTWorkoutPlanItem.fromJson(Map<String, dynamic> json) {
        return PTWorkoutPlanItem(
          id: json['id'] as int,
          title: json['title'] as String,
          assignedUsers: (json['assignedUsers'] as List<dynamic>)
              .cast<Map<String, dynamic>>()
              .map((item) => AssignedUsers.fromJson(item))
              .toList(),
          workouts: (json['workouts'] as List<dynamic>)
              .cast<Map<String, dynamic>>()
              .map((item) => WorkoutPlanItem.fromJson(item))
              .toList(),
          ptId: json['ptId'] as int,
        );
      }
    }
    
    class AssignedUsers {
      int id;
      String title;
    
      AssignedUsers({required this.id, required this.title});
    
      factory AssignedUsers.fromJson(Map<String, dynamic> json) {
        return AssignedUsers(id: json['id'] as int, title: json['title'] as String);
      }
    }
    
    class WorkoutPlanItem {
      int id;
      String title;
      int duration;
      int sets;
      int rest;
    
      WorkoutPlanItem(
          {required this.id,
          required this.title,
          required this.duration,
          required this.sets,
          required this.rest});
    
      factory WorkoutPlanItem.fromJson(Map<String, dynamic> json) {
        return WorkoutPlanItem(
          id: json['id'] as int,
          title: json['title'] as String,
          duration: json['duration'] as int,
          sets: json['sets'] as int,
          rest: json['rest'] as int,
        );
      }
    }
    

    更新:您也可以尝试将您的方法更改为:

    Future<Map<String, dynamic>> get({url}) async {
      final response = await http.get(baseUrl + url, headers: headers);
      print(response.statusCode);
    
      final res = json.decode(response.body) as Map<String, dynamic>;
      return res;
    }
    

    【讨论】:

    • 两种解决方案都遇到同样的问题
    • @chumberjosh 通过更改您的 get 方法更新了我的答案。
    猜你喜欢
    • 2019-08-07
    • 2021-07-11
    • 2020-08-20
    • 2021-01-17
    • 2019-09-26
    • 2021-05-21
    • 1970-01-01
    • 2020-11-05
    • 2021-09-07
    相关资源
    最近更新 更多