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

Dart使用GenericListResponse解析接口报List<dynamic>类型不匹配错误

错误根因

Dart 对泛型集合不存在自动递归类型转换:json.decode 反序列化接口响应时,所有 JSON 数组默认会被解析为 List<dynamic> 类型,不会自动把数组内的元素转换成你声明的 ProductReadDto 类型。你当前实现的 GenericListResponse.fromMap 直接将 json["result"] 赋值给 List<T>? 类型的 result 字段,本质是把 List<dynamic> 强转为 List<ProductReadDto> 使用,运行时就会触发类型不匹配异常。
单对象版本的 GenericResponse 也存在相同隐患,只是当前报错场景是列表返回接口,问题先暴露在列表解析逻辑上。

修复方案

给两个泛型响应类增加类型解析回调参数,在构造响应对象时手动完成 result 字段的类型转换,不需要依赖第三方库即可解决问题。
首先修改两个泛型类的实现:

import 'dart:convert';

class GenericResponse<T> {
  GenericResponse({
    this.result,
    this.status = 200,
    this.message = "",
  });

  factory GenericResponse.fromMap(
    final Map<String, dynamic> json, {
    required T Function(dynamic) parseResult,
  }) => GenericResponse(
        status: json["status"] ?? 200,
        message: json["message"] ?? "",
        result: json["result"] == null ? null : parseResult(json["result"]),
      );

  factory GenericResponse.fromJson(
    final String str, {
    required T Function(dynamic) parseResult,
  }) => GenericResponse.fromMap(json.decode(str), parseResult: parseResult);

  final int status;
  final String message;
  final T? result;
}

class GenericListResponse<T> {
  GenericListResponse({
    this.result,
    this.status = 200,
    this.message = "",
  });

  factory GenericListResponse.fromMap(
    final dynamic json, {
    required T Function(dynamic) parseItem,
  }) => GenericListResponse(
        status: json["status"] ?? 200,
        message: json["message"] ?? "",
        result: json["result"] == null 
          ? null 
          : (json["result"] as List<dynamic>).map((item) => parseItem(item)).toList(),
      );

  factory GenericListResponse.fromJson(
    final String str, {
    required T Function(dynamic) parseItem,
  }) => GenericListResponse.fromMap(json.decode(str), parseItem: parseItem);

  final int status;
  final String message;
  final List<T>? result;
}

然后修改接口调用代码,传入对应类型的解析逻辑即可,假设ProductReadDto已经实现了fromMap命名构造函数用于反序列化:

Future<void> read({
  required final Function(GenericListResponse<ProductReadDto>) onResponse,
  required final Function(GenericResponse response) onError,
}) async =>
     httpGet(
      url: "$baseUrl/Product/${type.title}",
      action: (Response response) => onResponse(
        GenericListResponse<ProductReadDto>.fromMap(
          response.body,
          // 传入列表单个元素的转换逻辑
          parseItem: (itemJson) => ProductReadDto.fromMap(itemJson as Map<String, dynamic>),
        )
      ),
      error: (Response response) => onError(
        GenericResponse.fromMap(
          response.body,
          // 错误场景可根据实际返回结构调整result解析逻辑
          parseResult: (err) => err,
        )
      ),
    );

如果项目中使用了json_serializable等自动序列化库,只需要把parseItem、parseResult参数里的转换逻辑替换为对应生成的反序列化方法即可,整体逻辑不需要改动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 17:01:04