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

Flutter新手JSON解析报错:类型不匹配问题求助与代码修复

嘿,刚仔细看了你的代码和遇到的两个错误,这俩问题其实都是JSON结构和代码里的数据类型不匹配导致的,我来一步步帮你搞定~

先拆解错误原因

  1. 第一个错误:'_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List<dynamic>'
    你的本地JSON文件应该是一个包含数组的对象(比如{"restaurants": [{}, {}, ...]}),但你直接把整个JSON响应当成List来解析了,jsonDecode(json)返回的是Map而非List,所以parseArticles里的类型转换就炸了。

  2. 第二个错误:type List dynamic is not a subtype of type 'List'
    看你Resto类里把foods和drinks定义成了Map<String, String>,但实际JSON里的menus.foods和menus.drinks是数组(比如[{"name": "炸鸡"}, ...]),类型完全不匹配,自然报错。


一步步修复代码

1. 修复JSON解析逻辑(解决第一个错误)

修改parseArticles函数,先把JSON解析成Map,再取出里面的餐厅数组:

List<Resto> parseArticles(String json) {
  if (json == null) {
    return [];
  }
  // 先解析为Map,再提取restaurants数组
  final Map<String, dynamic> parsedMap = jsonDecode(json);
  final List<dynamic> restoList = parsedMap['restaurants'];
  return restoList.map((json) => Resto.fromJson(json)).toList();
}

2. 修复Resto类的字段类型(解决第二个错误)

把foods和drinks改成List<String>,并修改fromJson方法来正确解析数组里的name字段:

import 'dart:convert';

class Resto {
  String id;
  String name;
  String description;
  String pictureId;
  String city;
  double rating;
  List<String> foods; // 改为List<String>
  List<String> drinks; // 改为List<String>

  Resto({
    this.id,
    this.name,
    this.description,
    this.pictureId,
    this.city,
    this.rating,
    this.foods,
    this.drinks,
  });

  Resto.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
    description = json['description'];
    pictureId = json['pictureId'];
    city = json['city'];
    rating = json['rating']?.toDouble(); // 加空安全处理,防止rating为null

    // 解析foods数组,提取每个元素的name
    final List<dynamic> foodList = json['menus']['foods'];
    foods = foodList.map((food) => food['name'] as String).toList();

    // 解析drinks数组,提取每个元素的name
    final List<dynamic> drinkList = json['menus']['drinks'];
    drinks = drinkList.map((drink) => drink['name'] as String).toList();
  }
}

3. 完善FutureBuilder的状态处理(避免崩溃)

你原来的代码直接用snapshot.data,没处理加载中、出错、空数据的情况,很容易崩溃,加上这些判断:

body: FutureBuilder<String>(
  future: DefaultAssetBundle.of(context).loadString('assets/local_restaurant.json'),
  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 || snapshot.data == null) {
      return const Center(child: Text('没有餐厅数据'));
    }

    // 解析并渲染列表
    final List<Resto> restos = parseArticles(snapshot.data!);
    return ListView.builder(
      itemCount: restos.length,
      itemBuilder: (context, index) {
        return _buildArticleItem(context, restos[index]);
      },
    );
  },
),

最后验证你的JSON结构

确保assets/local_restaurant.json的结构类似这样(如果你的键名不是restaurants,要对应修改parseArticles里的键):

{
  "restaurants": [
    {
      "id": "rqdv5juczeskfw1e867",
      "name": "Melting Pot",
      "description": "Lorem ipsum dolor sit amet...",
      "pictureId": "https://restaurant-api.dicoding.dev/images/large/14",
      "city": "Medan",
      "rating": 4.2,
      "menus": {
        "foods": [{"name": "Paket roti bakar"}, {"name": "Kebab"}],
        "drinks": [{"name": "Es Teh"}, {"name": "Es Jeruk"}]
      }
    }
  ]
}

这样修改后,两个错误应该都能解决啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:31:36