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

Flutter解析JSON报错List<dynamic>不是List<String>子类型如何解决

错误原因

jsonDecode 解析JSON后,所有数组类型默认都会被推断为List<dynamic>,Dart不支持List<dynamic>到List<String>的隐式类型转换,所以无论是实体类赋值还是路由传参时直接传递videos字段,都会触发类型不匹配报错。

解决方案

方案一:全链路使用实体类(推荐,可维护性更高)

1. 修正JSON实体类的fromJson方法,显式转换videos的类型

factory VideoDetails.fromJson(Map<String, dynamic> json) {
  return VideoDetails(
    name: json['name'] as String,
    playList: json['playList'] as String,
    // 两种转换方式二选一即可
    videos: List<String>.from(json["videos"]),
    // 或者用 videos: (json["videos"] as List).cast<String>(),
  );
}

2. 修正读取JSON的方法,把解析结果转换为实体类列表

Future<List<VideoDetails>> getPlayerList() async {
  String data = await DefaultAssetBundle.of(context).loadString("assets/lists/v-player.json");
  final jsonResult = jsonDecode(data) as List;
  return jsonResult.map((item) => VideoDetails.fromJson(item)).toList();
}

3. 修正FutureBuilder代码,使用强类型的实体类

FutureBuilder<List<VideoDetails>>(
  future: getPlayerList(),
  builder: (BuildContext context, AsyncSnapshot<List<VideoDetails>> snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const Center(child: Text("Loading..."));
    }
    if (snapshot.hasError) {
      return Center(child: Text("加载失败:${snapshot.error}"));
    }
    final list = snapshot.data!;
    return ListView.builder(
        itemCount: list.length,
        itemBuilder: (context, index) {
          var item = list[index];
          return ListTile(
            leading: const FaIcon(FontAwesomeIcons.video),
            title: Text(item.name),
            trailing: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                Text('${item.videos.length}'),
                const Icon(Icons.arrow_forward_ios_rounded),
              ],
            ),
            onTap: () {
              if(item.videos.isNotEmpty) {
                Navigator.pushNamed(context, '/player', arguments: VideoArguments(
                    item.name,
                    item.playList,
                    item.videos,
                ));
              } else {
                //...
              }
            },
          );
        }
    );
  }
)

方案二:临时修复(仅解决当前传参报错)

如果不想修改整体解析逻辑,直接在路由传参的位置对videos做类型转换即可:

Navigator.pushNamed(context, '/player', arguments: VideoArguments(
    item['name'] as String,
    item['playList'] as String,
    List<String>.from(item['videos']),
));

额外注意事项

你提供的JSON示例中videos数组最后一个元素末尾多了一个逗号,属于JSON语法错误,解析时会报错,需要去掉:

"videos": [
  "q2ZZlUsnX5Y",
  "ANpas6oyZjw",
  "5qwP-SOEdKg",
  "hWm62l-d3DE",
  "F07RJdvQ77w" // 移除末尾多余的逗号
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:36:01