类型“列表<动态>"不是'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;
}
}
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.