类型“列表<动态>"不是'String'类型的子类型 [英] type 'List<dynamic>' is not a subtype of type 'String'

查看:94
本文介绍了类型“列表<动态>"不是'String'类型的子类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

它包含许多列表和嵌套对象.我需要显示json文件中的所有DishName

Json URL地址: Json地址!!检查一下

我想在我的应用程序中显示DishName,其中json列表中有很多菜名. 我使用立即解析json网站解析了json文件. 但是现在我不知道如何在我的应用程序上启用它

i wanted to display the DishName in to my app in which there are lots of dishname in the json list. i parsed the json file using instantly parse json website. But now i dont know how to implent it on my app

我写的代码:

body: Container(
     child: Center(
      child: FutureBuilder(
        future:
            DefaultAssetBundle.of(context).loadString('jsons/data.json'),
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return CircularProgressIndicator();
          }
          var myData = jsonDecode(snapshot.data);
          final welcome = welcomeFromJson(myData);

          print(myData.length);
          return ListView.builder(
            itemBuilder: (BuildContext context, int index) {
              return Card(
                  child: ListTile(
                title: Text(welcome[index]
                    .tableMenuList[index]
                    .categoryDishes[index]
                    .dishName),
              ));
            },
            itemCount: myData == null ? 0 : myData.length,
          );
        },
      ),
    ),
  ),

我遇到错误:列表"类型不是字符串"类型的子类型

i am getting error : type 'List' is not a subtype of type 'String'

这是json类:-

// To parse this JSON data, do
//
//     final welcome = welcomeFromJson(jsonString);

import 'dart:convert';

List<Welcome> welcomeFromJson(String str) =>
    List<Welcome>.from(json.decode(str).map((x) => Welcome.fromJson(x)));

String welcomeToJson(List<Welcome> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Welcome {
  String restaurantId;
  String restaurantName;
  String restaurantImage;
  String tableId;
  String tableName;
  String branchName;
  String nexturl;
  List<TableMenuList> tableMenuList;

  Welcome({
    this.restaurantId,
    this.restaurantName,
    this.restaurantImage,
    this.tableId,
    this.tableName,
    this.branchName,
    this.nexturl,
    this.tableMenuList,
  });

  factory Welcome.fromJson(Map<String, dynamic> json) => Welcome(
        restaurantId: json["restaurant_id"],
        restaurantName: json["restaurant_name"],
        restaurantImage: json["restaurant_image"],
        tableId: json["table_id"],
        tableName: json["table_name"],
        branchName: json["branch_name"],
        nexturl: json["nexturl"],
        tableMenuList: List<TableMenuList>.from(
            json["table_menu_list"].map((x) => TableMenuList.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "restaurant_id": restaurantId,
        "restaurant_name": restaurantName,
        "restaurant_image": restaurantImage,
        "table_id": tableId,
        "table_name": tableName,
        "branch_name": branchName,
        "nexturl": nexturl,
        "table_menu_list":
            List<dynamic>.from(tableMenuList.map((x) => x.toJson())),
      };
}

class TableMenuList {
  String menuCategory;
  String menuCategoryId;
  String menuCategoryImage;
  String nexturl;
  List<CategoryDish> categoryDishes;

  TableMenuList({
    this.menuCategory,
    this.menuCategoryId,
    this.menuCategoryImage,
    this.nexturl,
    this.categoryDishes,
  });

  factory TableMenuList.fromJson(Map<String, dynamic> json) => TableMenuList(
        menuCategory: json["menu_category"],
        menuCategoryId: json["menu_category_id"],
        menuCategoryImage: json["menu_category_image"],
        nexturl: json["nexturl"],
        categoryDishes: List<CategoryDish>.from(
            json["category_dishes"].map((x) => CategoryDish.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "menu_category": menuCategory,
        "menu_category_id": menuCategoryId,
        "menu_category_image": menuCategoryImage,
        "nexturl": nexturl,
        "category_dishes":
            List<dynamic>.from(categoryDishes.map((x) => x.toJson())),
      };
}

class AddonCat {
  String addonCategory;
  String addonCategoryId;
  int addonSelection;
  String nexturl;
  List<CategoryDish> addons;

  AddonCat({
    this.addonCategory,
    this.addonCategoryId,
    this.addonSelection,
    this.nexturl,
    this.addons,
  });

  factory AddonCat.fromJson(Map<String, dynamic> json) => AddonCat(
        addonCategory: json["addon_category"],
        addonCategoryId: json["addon_category_id"],
        addonSelection: json["addon_selection"],
        nexturl: json["nexturl"],
        addons: List<CategoryDish>.from(
            json["addons"].map((x) => CategoryDish.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "addon_category": addonCategory,
        "addon_category_id": addonCategoryId,
        "addon_selection": addonSelection,
        "nexturl": nexturl,
        "addons": List<dynamic>.from(addons.map((x) => x.toJson())),
      };
}

class CategoryDish {
  String dishId;
  String dishName;
  double dishPrice;
  String dishImage;
  DishCurrency dishCurrency;
  int dishCalories;
  String dishDescription;
  bool dishAvailability;
  int dishType;
  String nexturl;
  List<AddonCat> addonCat;

  CategoryDish({
    this.dishId,
    this.dishName,
    this.dishPrice,
    this.dishImage,
    this.dishCurrency,
    this.dishCalories,
    this.dishDescription,
    this.dishAvailability,
    this.dishType,
    this.nexturl,
    this.addonCat,
  });

  factory CategoryDish.fromJson(Map<String, dynamic> json) => CategoryDish(
        dishId: json["dish_id"],
        dishName: json["dish_name"],
        dishPrice: json["dish_price"].toDouble(),
        dishImage: json["dish_image"],
        dishCurrency: dishCurrencyValues.map[json["dish_currency"]],
        dishCalories: json["dish_calories"],
        dishDescription: json["dish_description"],
        dishAvailability: json["dish_Availability"],
        dishType: json["dish_Type"],
        nexturl: json["nexturl"] == null ? null : json["nexturl"],
        addonCat: json["addonCat"] == null
            ? null
            : List<AddonCat>.from(
                json["addonCat"].map((x) => AddonCat.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "dish_id": dishId,
        "dish_name": dishName,
        "dish_price": dishPrice,
        "dish_image": dishImage,
        "dish_currency": dishCurrencyValues.reverse[dishCurrency],
        "dish_calories": dishCalories,
        "dish_description": dishDescription,
        "dish_Availability": dishAvailability,
        "dish_Type": dishType,
        "nexturl": nexturl == null ? null : nexturl,
        "addonCat": addonCat == null
            ? null
            : List<dynamic>.from(addonCat.map((x) => x.toJson())),
      };
}

enum DishCurrency { SAR }

final dishCurrencyValues = EnumValues({"SAR": DishCurrency.SAR});

class EnumValues<T> {
  Map<String, T> map;
  Map<T, String> reverseMap;

  EnumValues(this.map);

  Map<T, String> get reverse {
    if (reverseMap == null) {
      reverseMap = map.map((k, v) => new MapEntry(v, k));
    }
    return reverseMap;
  }
}

推荐答案

我个人使用此方法从JSON

I personally use this one for generating dart classes from JSON https://javiercbk.github.io/json_to_dart/

根据我的经验,大多数此类自动类生成器在某种程度上存在缺陷,并且优良作法是手动检查生成的飞镖.或者,如果运气好的话,可以走堆栈跟踪来查看解析失败的地方(通常是在处理int并从我所看到的结果翻倍的情况下).

From my experience most of these automatic class builders are flawed to some extent and it is good practice to go over the generated dart manually. Or try your luck and walk the stack trace to see where parsing failed (usually when handling int and double from what I've seen).

无论如何,回到代码的问题,我发现您正在滥用索引,并且通常在json数据结构方面遇到问题:

Anyhow back to your problem, from looking at your code I see you are misusing indexes and generally having problems with json data structure:

               title: Text(welcome[index]
                .tableMenuList[index]
                .categoryDishes[index]
                .dishName),

上面的代码可以轻松引发"RangeError(索引):无效值:不在范围内……"(如果welcome [2]仅具有1个tableMenuList,则为示例).即使上面所有这些数组的长度都相同,您仍将无法获得预期的结果..该列表最终将显示第一菜单中的第一餐和第一类菜肴,然后第二餐将是第二餐菜单和第二餐厅.

The code above can easily throw "RangeError (index): Invalid value: Not in range..." (example if welcome[ 2 ] has only 1 tableMenuList). Even if all those arrays above are somehow the same length you would still not get the expected result.. The list would end up showing you 1st meal from the 1st menu list and 1st category dish, then next one would be 2nd meal from the 2nd menu and the 2nd restaurant.

由于与上述相同的原因,以下代码还不够:

Also because of the same reason as above the following code isn't enough:

itemCount: myData == null ? 0 : myData.length,

您需要为正在使用的每个列表都有一个itemCount.

You need to have an itemCount for each of those lists you are using.

我已经修改了您的代码以使用给定的JSON,并更改了一些内容,最终看起来

I've modified your code to work with the given JSON and changed a few things, in the end it looks like this.

我正在发布源代码,希望它可以使您更清楚:

I'm posting my source bellow, hopefully it will make things clearer for you:

pubspec.yaml

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.2
  http: any

welcome_model.dart

welcome_model.dart

class Welcome {
  String restaurantId;
  String restaurantName;
  String restaurantImage;
  String tableId;
  String tableName;
  String branchName;
  String nexturl;
  List<TableMenuList> tableMenuList;

  Welcome(
      {this.restaurantId,
        this.restaurantName,
        this.restaurantImage,
        this.tableId,
        this.tableName,
        this.branchName,
        this.nexturl,
        this.tableMenuList});

  Welcome.fromJson(Map<String, dynamic> json) {
    restaurantId = json['restaurant_id'];
    restaurantName = json['restaurant_name'];
    restaurantImage = json['restaurant_image'];
    tableId = json['table_id'];
    tableName = json['table_name'];
    branchName = json['branch_name'];
    nexturl = json['nexturl'];
    if (json['table_menu_list'] != null) {
      tableMenuList = new List<TableMenuList>();
      json['table_menu_list'].forEach((v) {
        tableMenuList.add(new TableMenuList.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['restaurant_id'] = this.restaurantId;
    data['restaurant_name'] = this.restaurantName;
    data['restaurant_image'] = this.restaurantImage;
    data['table_id'] = this.tableId;
    data['table_name'] = this.tableName;
    data['branch_name'] = this.branchName;
    data['nexturl'] = this.nexturl;
    if (this.tableMenuList != null) {
      data['table_menu_list'] =
          this.tableMenuList.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class TableMenuList {
  String menuCategory;
  String menuCategoryId;
  String menuCategoryImage;
  String nexturl;
  List<CategoryDishes> categoryDishes;

  TableMenuList(
      {this.menuCategory,
        this.menuCategoryId,
        this.menuCategoryImage,
        this.nexturl,
        this.categoryDishes});

  TableMenuList.fromJson(Map<String, dynamic> json) {
    menuCategory = json['menu_category'];
    menuCategoryId = json['menu_category_id'];
    menuCategoryImage = json['menu_category_image'];
    nexturl = json['nexturl'];
    if (json['category_dishes'] != null) {
      categoryDishes = new List<CategoryDishes>();
      json['category_dishes'].forEach((v) {
        categoryDishes.add(new CategoryDishes.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['menu_category'] = this.menuCategory;
    data['menu_category_id'] = this.menuCategoryId;
    data['menu_category_image'] = this.menuCategoryImage;
    data['nexturl'] = this.nexturl;
    if (this.categoryDishes != null) {
      data['category_dishes'] =
          this.categoryDishes.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class CategoryDishes {
  String dishId;
  String dishName;
  double dishPrice;
  String dishImage;
  String dishCurrency;
  double dishCalories;
  String dishDescription;
  bool dishAvailability;
  int dishType;
  String nexturl;
  List<AddonCat> addonCat;

  CategoryDishes(
      {this.dishId,
        this.dishName,
        this.dishPrice,
        this.dishImage,
        this.dishCurrency,
        this.dishCalories,
        this.dishDescription,
        this.dishAvailability,
        this.dishType,
        this.nexturl,
        this.addonCat});

  CategoryDishes.fromJson(Map<String, dynamic> json) {
    dishId = json['dish_id'];
    dishName = json['dish_name'];
    dishPrice = json['dish_price'];
    dishImage = json['dish_image'];
    dishCurrency = json['dish_currency'];
    dishCalories = json['dish_calories'];
    dishDescription = json['dish_description'];
    dishAvailability = json['dish_Availability'];
    dishType = json['dish_Type'];
    nexturl = json['nexturl'];
    if (json['addonCat'] != null) {
      addonCat = new List<AddonCat>();
      json['addonCat'].forEach((v) {
        addonCat.add(new AddonCat.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['dish_id'] = this.dishId;
    data['dish_name'] = this.dishName;
    data['dish_price'] = this.dishPrice;
    data['dish_image'] = this.dishImage;
    data['dish_currency'] = this.dishCurrency;
    data['dish_calories'] = this.dishCalories;
    data['dish_description'] = this.dishDescription;
    data['dish_Availability'] = this.dishAvailability;
    data['dish_Type'] = this.dishType;
    data['nexturl'] = this.nexturl;
    if (this.addonCat != null) {
      data['addonCat'] = this.addonCat.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class AddonCat {
  String addonCategory;
  String addonCategoryId;
  int addonSelection;
  String nexturl;
  List<Addons> addons;

  AddonCat(
      {this.addonCategory,
        this.addonCategoryId,
        this.addonSelection,
        this.nexturl,
        this.addons});

  AddonCat.fromJson(Map<String, dynamic> json) {
    addonCategory = json['addon_category'];
    addonCategoryId = json['addon_category_id'];
    addonSelection = json['addon_selection'];
    nexturl = json['nexturl'];
    if (json['addons'] != null) {
      addons = new List<Addons>();
      json['addons'].forEach((v) {
        addons.add(new Addons.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['addon_category'] = this.addonCategory;
    data['addon_category_id'] = this.addonCategoryId;
    data['addon_selection'] = this.addonSelection;
    data['nexturl'] = this.nexturl;
    if (this.addons != null) {
      data['addons'] = this.addons.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class Addons {
  String dishId;
  String dishName;
  double dishPrice;
  String dishImage;
  String dishCurrency;
  double dishCalories;
  String dishDescription;
  bool dishAvailability;
  int dishType;

  Addons(
      {this.dishId,
        this.dishName,
        this.dishPrice,
        this.dishImage,
        this.dishCurrency,
        this.dishCalories,
        this.dishDescription,
        this.dishAvailability,
        this.dishType});

  Addons.fromJson(Map<String, dynamic> json) {
    dishId = json['dish_id'];
    dishName = json['dish_name'];
    dishPrice = json['dish_price'];
    dishImage = json['dish_image'];
    dishCurrency = json['dish_currency'];
    dishCalories = json['dish_calories'];
    dishDescription = json['dish_description'];
    dishAvailability = json['dish_Availability'];
    dishType = json['dish_Type'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['dish_id'] = this.dishId;
    data['dish_name'] = this.dishName;
    data['dish_price'] = this.dishPrice;
    data['dish_image'] = this.dishImage;
    data['dish_currency'] = this.dishCurrency;
    data['dish_calories'] = this.dishCalories;
    data['dish_description'] = this.dishDescription;
    data['dish_Availability'] = this.dishAvailability;
    data['dish_Type'] = this.dishType;
    return data;
  }
}

welcome_page.dart

welcome_page.dart

import 'package:flutter/material.dart';
import 'welcome_model.dart';
import 'dart:async';
import 'dart:io';
import 'dart:convert';
import 'package:http/http.dart' as http;



class WelcomePage extends StatefulWidget {
  @override
  _WelcomePageState createState() => new _WelcomePageState();

}

class _WelcomePageState extends State<WelcomePage> {
  List<Welcome> welcomeList;
  bool isLoading = true;
  int selectedRestaurantIndex = 0;
  String titleString = "Restaurant";

  @override
  void initState() {
    super.initState();
    _fetchData();
  }


  @override
  void setState(fn) {
    if(mounted){
      super.setState(fn);
    }
  }


  @override
  void dispose() {
    super.dispose();
  }

  _fetchData() async{
    setState(() {
      isLoading = true;
    });
    // String url = Uri.encodeFull("http://www.mocky.io/v2/5dfccffc310000efc8d2c1ad"); // original json has only one restaurant
    // the one bellow has 3 restaurants,
    // 1st one was left untouched,
    // 2nd one (Steak house) has only "From The Barnyard" and "Fast Food" menu types
    // 3rd one (Bistro cafe) has only "Fresh From The Sea" and "Fast Food" menu types
    String url = Uri.encodeFull("http://www.mocky.io/v2/5e4aa68c2f0000690097d3f6");
    var parsedJson;
    try {
      http.Response response = await http.get(url).
      timeout(Duration(seconds: 10));
      if (response.statusCode == 200) {
        if (response.bodyBytes != null) {
           parsedJson = json.decode(utf8.decode(response.bodyBytes));
        }
      } else {
        print('RESPONSE CODE != 200 !');
      }
    } on TimeoutException catch (e) {
      print('Error: $e');
    } on SocketException catch (e) {
      print('Error: $e');
    } on Error catch (e) {
      print('Error: $e');
    }

    if(parsedJson!=null){
        if(parsedJson.length>0){
          welcomeList = new List<Welcome>();
          for(int i=0; i<parsedJson.length; i++) {
            try {
              welcomeList.add(Welcome.fromJson(parsedJson[i]));
            } catch (e, s){
              print('Eroor parsing from JSON! For # $i');
              print('Error: $e');
              print('Stacktrace: $s');
            }
          }
          if(welcomeList[0]!=null && welcomeList[0].restaurantName!=null) {
             titleString = welcomeList[0].restaurantName;
          }
        }
    }

    setState(() {
      isLoading = false;
    });

  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
        backgroundColor: Colors.white,
        appBar: AppBar(
          iconTheme: IconThemeData(
            color: Colors.white,
          ),
          title: Text(titleString),
          centerTitle: true,
        ),
        drawer: Drawer(
          child: ListView(
                padding: EdgeInsets.zero,
                children: <Widget>[
                  DrawerHeader(
                    child: Text("Select a restaurant", style: TextStyle(color: Colors.white, fontSize: 28),textAlign: TextAlign.center,
                    ),
                    decoration: BoxDecoration(
                      color: Theme.of(context).primaryColor,
                    ),
                  ),
                  (welcomeList!=null && welcomeList.length>0) ?
                  ListView.builder(
                      shrinkWrap: true,
                      physics: ClampingScrollPhysics(),
                      itemCount: welcomeList.length,
                      itemBuilder: (BuildContext context, int index) {
                        return Padding(
                            padding: EdgeInsets.all(8),
                            child: RaisedButton(
                              onPressed: () {
                                setState(() {
                                  selectedRestaurantIndex = index;
                                  titleString = welcomeList[index].restaurantName.toString();
                                });
                                Navigator.pop(context);
                              },
                              padding: EdgeInsets.all(12),
                              child: Text(welcomeList[index].restaurantName.toString()),
                          )
                        );
                        ;}
                  )
                  : Text("No restaurants loaded...")
                ]
            )
        ),
        body: (isLoading)
          ? Center(child: CircularProgressIndicator(),)
          : Container(
              child: Center(
                 child: ListView.builder(
                  itemBuilder: (BuildContext context, int index1) {
                    return Card(
                        child: ListTile(
                          subtitle: Text(welcomeList[selectedRestaurantIndex].tableMenuList[index1].menuCategory.toString()),
                          title: ListView.builder(
                            shrinkWrap: true,
                            physics: ClampingScrollPhysics(),
                            itemBuilder: (BuildContext context, int index2) {
                            return Card(
                                child: ListTile(
                                    title: Text(welcomeList[selectedRestaurantIndex].tableMenuList[index1].categoryDishes[index2].dishName.toString()),
                                ));
                          },
                          itemCount: (welcomeList[selectedRestaurantIndex].tableMenuList[index1] == null || welcomeList[selectedRestaurantIndex].tableMenuList[index1].categoryDishes == null) ? 0 : (welcomeList[selectedRestaurantIndex].tableMenuList[index1].categoryDishes.length) ,)
                        )
                    );
                  },
                  itemCount: (welcomeList == null || welcomeList[selectedRestaurantIndex] == null || welcomeList[selectedRestaurantIndex].tableMenuList == null) ? 0 : (welcomeList[selectedRestaurantIndex].tableMenuList.length) ,
                )
              ),
            ),
    );
  }
}

带有3个餐厅的JSON 此处

JSON with 3 restaurants here or here.

这篇关于类型“列表&lt;动态&gt;"不是'String'类型的子类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆