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

Flutter运行报List<dynamic>不是Map<String,dynamic>子类型错误如何解决

错误原因

你的代码存在3处类型不匹配问题,直接触发了类型转换报错:

  1. 本地JSON的根节点是Map<String, dynamic>类型,但你在parseRestaurant方法中直接将jsonDecode的返回值强转为List,类型不匹配
  2. JSON中根节点下的restaurants是数组类型,但你在RestaurantDetail类中将该字段定义为单个Restaurant对象
  3. JSON中menus下的foods、drinks都是数组类型,但你在Menus类中将两个字段分别定义为单个Foods、Drinks对象

修复后的代码

模型类代码

import 'dart:convert';

class RestaurantResponse {
  late List<Restaurant> restaurants;

  RestaurantResponse({required this.restaurants});

  RestaurantResponse.fromJson(Map<String, dynamic> json) {
    // 处理restaurants数组
    var restaurantsList = json['restaurants'] as List;
    restaurants = restaurantsList.map((item) => Restaurant.fromJson(item)).toList();
  }
}

class Restaurant {
  late String id;
  late String name;
  late String description;
  late String pictureId;
  late String city;
  late double rating;
  late Menus menus;

  Restaurant({
    required this.id,
    required this.name,
    required this.description,
    required this.pictureId,
    required this.city,
    required this.rating,
    required this.menus,
  });

  Restaurant.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
    description = json['description'];
    pictureId = json['pictureId'];
    city = json['city'];
    rating = json['rating']?.toDouble() ?? 0.0; // 兼容int类型的评分
    menus = Menus.fromJson(json['menus']);
  }
}

class Menus {
  late List<Food> foods;
  late List<Drink> drinks;

  Menus({
    required this.foods,
    required this.drinks,
  });

  Menus.fromJson(Map<String, dynamic> json) {
    // 处理食物数组
    var foodsList = json['foods'] as List;
    foods = foodsList.map((item) => Food.fromJson(item)).toList();
    // 处理饮品数组
    var drinksList = json['drinks'] as List;
    drinks = drinksList.map((item) => Drink.fromJson(item)).toList();
  }
}

class Food {
  late String name;

  Food({required this.name});

  Food.fromJson(Map<String, dynamic> json) {
    name = json['name'];
  }
}

class Drink {
  late String name;

  Drink({required this.name});

  Drink.fromJson(Map<String, dynamic> json) {
    name = json['name'];
  }
}

// 修正解析方法
List<Restaurant> parseRestaurant(String? json) {
  if (json == null) {
    return [];
  }
  final Map<String, dynamic> rootJson = jsonDecode(json);
  final response = RestaurantResponse.fromJson(rootJson);
  return response.restaurants;
}

首页代码

补充了FutureBuilder的加载、错误状态兼容,以及图片加载失败的兜底处理:

import 'package:flutter/material.dart';
import 'package:restaurant/data/restaurant.dart';
import 'package:restaurant/style/theme.dart';

class HomePage extends StatelessWidget {
  static const routeName = '/article_list';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: kBackgroundColor,
      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}'));
          }
          final List<Restaurant> restaurants = parseRestaurant(snapshot.data);
          return ListView.builder(
            itemCount: restaurants.length,
            itemBuilder: (context, index) {
              return _buildRestaurantItem(context, restaurants[index]);
            },
          );
        },
      ),
    );
  }

  Widget _buildRestaurantItem(BuildContext context, Restaurant restaurant) {
    return ListTile(
      contentPadding:
          const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
      leading: Image.network(
        restaurant.pictureId,
        width: 100,
        fit: BoxFit.cover,
        errorBuilder: (context, error, stackTrace) {
          return const Icon(Icons.broken_image, size: 100);
        },
      ),
      title: Text(restaurant.name),
      subtitle: Text(restaurant.city),
      trailing: Text('⭐ ${restaurant.rating}'),
      onTap: () {},
    );
  }
}

内容的提问来源于stack exchange,提问作者muhammad alam nur haris

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 00:48:03