Flutter调用TMDB API遇类型错误:String无法转为Map<dynamic, dynamic>
解决TMDB API请求中的类型转换错误
错误根源
你遇到的两个错误都是JSON解析时的类型不匹配导致的,和TMDB返回的结构(外层是包含results数组的对象)不对应:
- 第一个错误:尝试将某个字符串值当作
Map<dynamic,dynamic>处理,比如未正确解析整个响应就直接访问内部字段 - 第二个错误:改成
var后,误将字符串当作数组索引使用(数组只能用整数索引)
分步解决
1. 定义匹配TMDB结构的实体类
创建与返回JSON严格对应的实体类,避免类型不匹配:
Movie实体类(对应单条电影数据)
class Movie { final bool adult; final String? backdropPath; final List<int> genreIds; final int id; final String originalLanguage; final String originalTitle; final String overview; final double popularity; final String? posterPath; final String releaseDate; final String title; final bool video; final double voteAverage; final int voteCount; Movie({ required this.adult, this.backdropPath, required this.genreIds, required this.id, required this.originalLanguage, required this.originalTitle, required this.overview, required this.popularity, this.posterPath, required this.releaseDate, required this.title, required this.video, required this.voteAverage, required this.voteCount, }); factory Movie.fromJson(Map<String, dynamic> json) { return Movie( adult: json['adult'] as bool, backdropPath: json['backdrop_path'] as String?, genreIds: (json['genre_ids'] as List).map((e) => e as int).toList(), id: json['id'] as int, originalLanguage: json['original_language'] as String, originalTitle: json['original_title'] as String, overview: json['overview'] as String, popularity: json['popularity'] as double, posterPath: json['poster_path'] as String?, releaseDate: json['release_date'] as String, title: json['title'] as String, video: json['video'] as bool, voteAverage: (json['vote_average'] as num).toDouble(), voteCount: json['vote_count'] as int, ); } }
外层响应实体类(对应TMDB返回的完整结构)
class MovieResponse { final int page; final List<Movie> results; final int totalPages; final int totalResults; MovieResponse({ required this.page, required this.results, required this.totalPages, required this.totalResults, }); factory MovieResponse.fromJson(Map<String, dynamic> json) { var resultsList = json['results'] as List; List<Movie> movies = resultsList.map((i) => Movie.fromJson(i as Map<String, dynamic>)).toList(); return MovieResponse( page: json['page'] as int, results: movies, totalPages: json['total_pages'] as int, totalResults: json['total_results'] as int, ); } }
2. 修正ApiService的解析逻辑
确保先将响应体解析为Map,再转换为实体类,避免直接操作字符串:
import 'dart:convert'; import 'package:http/http.dart' as http; class ApiService { final String baseUrl = 'https://api.themoviedb.org/3'; final String apiKey = '你的API_KEY'; // 替换为你的TMDB API Key Future<MovieResponse> getPopularMovies() async { final response = await http.get( Uri.parse('$baseUrl/movie/popular?api_key=$apiKey'), ); if (response.statusCode == 200) { // 必须先解析响应体为Map Map<String, dynamic> jsonData = jsonDecode(response.body); return MovieResponse.fromJson(jsonData); } else { throw Exception('加载电影数据失败'); } } }
3. 排查常见错误点
- 禁止直接将
response.body当作Map使用,必须通过jsonDecode()解析 - 遍历
results时,要操作数组元素(用整数索引或forEach),不要用字符串键访问(比如不要写results['title'],应该是results[0].title) - 字段类型严格匹配:比如
vote_average是num类型,需转为double;backdrop_path可能为null,设为String? - 检查API请求URL是否正确,确保包含
api_key参数,避免返回错误提示的JSON字符串
内容的提问来源于stack exchange,提问作者Seth
相关产品推荐
相关产品推荐

