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

Flutter请求公共API转换JSON为Dart对象出现NoSuchMethodError求助

问题核心原因

你看到的object_patch.dart抛出的NoSuchMethodError是Dart VM的统一异常入口,本质是业务代码中JSON解析的类型、结构和接口实际返回格式完全不匹配,和底层VM实现无关,具体错误点:

  • 接口返回的顶层是单个包含Search字段的JSON对象,不是Map列表,你在fetchMovie中把顶层解码结果强转为Map列表后直接调用map遍历,会触发方法不存在的异常。
  • Movie.fromJson中直接将原始JSON数组传给List<Search>.from(),没有对数组内的原始Map元素逐次调用Search.fromJson做类型转换,后续访问元素属性时会触发空引用、方法不存在的报错。
  • FutureBuilder定义的泛型、取值逻辑和实际返回结构错位,错误地将单个Movie对象当成Movie列表遍历访问。
修复方案

1. 重构模型类的JSON转换逻辑

补全数组元素的逐次转换,使用factory构造函数简化写法,避免空值隐患:

class Movie {
  List<Search> search;
  Movie({required this.search});

  factory Movie.fromJson(Map<String, dynamic> json) {
    final rawSearchList = json['Search'] as List;
    return Movie(
      search: rawSearchList.map((item) => Search.fromJson(item as Map<String, dynamic>)).toList(),
    );
  }
}

class Search {
  final String imdbID;
  final String title;
  final String year;
  final String poster;

  Search({
    required this.imdbID,
    required this.title,
    required this.year,
    required this.poster,
  });

  factory Search.fromJson(Map<String, dynamic> json) {
    return Search(
      imdbID: json['imdbID'] as String,
      title: json['Title'] as String,
      year: json['Year'] as String,
      poster: json['Poster'] as String,
    );
  }
}

2. 修正网络请求的返回结构

去掉错误的列表强转逻辑,对齐接口返回的单个对象结构:

Future<Movie> fetchMovie() async {
  // 新版本http包要求传入Uri对象,不要直接传字符串
  final response = await http.get(Uri.parse('https://fake-movie-database-api.herokuapp.com/api?s=batman'));
  // 顶层解码结果直接转为Map,不需要强转为列表
  final body = jsonDecode(response.body) as Map<String, dynamic>;
  return Movie.fromJson(body);
}

3. 修正界面渲染逻辑

对齐数据层级,补全加载、错误状态的判断,避免空指针:

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<Movie>(
      future: fetchMovie(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Center(child: CircularProgressIndicator());
        }
        if (snapshot.hasError) {
          return Center(child: Text('请求失败: ${snapshot.error}'));
        }
        if (snapshot.hasData) {
          final movieData = snapshot.data!;
          return ListView.builder(
            // 直接使用搜索结果的实际长度,不要硬编码itemCount
            itemCount: movieData.search.length,
            itemBuilder: (context, index) {
              final currentItem = movieData.search[index];
              return Container(
                margin: const EdgeInsets.symmetric(horizontal: 25, vertical: 16),
                height: 200,
                color: Colors.blue,
                child: Center(
                  child: Text(currentItem.title),
                ),
              );
            },
          );
        }
        return const SizedBox();
      },
    );
  }
}
避坑提示
  • 不要被object_patch.dart的报错路径误导,这个文件是Dart VM的内置实现,所有类型不匹配、调用不存在方法的异常最终都会路由到这里,和你修改Dart SDK源码没有关系。
  • List<自定义类>.from()方法只能转换已经是自定义类类型的列表,不会自动将原始Map转为自定义类实例,必须手动逐元素调用fromJson方法。
  • 取值时必须严格对齐接口JSON的层级关系,不要自行脑补嵌套结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.01 18:15:10