如何从列表映射 Flutter JSON 字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46229568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Map Flutter JSON Strings from List?
提问by Charles Jr
I'm successfully printing my response as String from my YouTube JSON url, but when I try to serialize through the "items" I get the following error Unhandled exception:
type 'List' is not a subtype of type 'Map' of 'json' where
List is from dart:core
Map is from dart:core
我成功地将我的响应从我的 YouTube JSON url 打印为字符串,但是当我尝试通过“项目”进行序列化时,我收到以下错误 Unhandled exception:
type 'List' is not a subtype of type 'Map' of 'json' where
List is from dart:core
Map is from dart:core
Here is my code...
这是我的代码...
class CardInfo {
//Constructor
String id;
String description;
String role;
//int score;
CardInfo.fromJson(Map json) {
this.id = json['vieoId'];
this.description = json['description'];
this.role = json['title'];
//this.score = json['score'];
}
}
Future getData() async {
String url = 'YouTube url';
var httpClient = createHttpClient();
var response = await httpClient.get(url);
Map data = JSON.decode(response.body);
//String ip = data['items'];
var ci = new CardInfo.fromJson(data['items']);
//print(data['items']);
print(ci.id);
//print(ci.description);
//print(ci.role);
if (!mounted) return;
setState(() {});
}
print(data['items']is printing, but print(ci.id)or any Card Info variables throws the above error.
print(data['items']正在打印,但是print(ci.id)或任何卡片信息变量都会引发上述错误。
**** Log of print(data);
**** 日志print(data);
{kind: youtube#searchListResponse, etag: "VPWTmrH7dFmi4s1RqrK4tLejnRI/P9wyOxsXEuXOCvj7znCun2-EykU", nextPageToken: CAMQAA, regionCode: US, pageInfo: {totalResults: 1000000, resultsPerPage: 3}, items: [{kind: youtube#searchResult, etag: "VPWTmrH7dFmi4s1RqrK4tLejnRI/Csl1kQhnOsbs0j4_336zJAN176k", id: {kind: youtube#video, videoId: e3pUxU_bE6w}, snippet: {publishedAt: 2017-09-14T09:43:17.000Z, channelId: UCbD8EppRX3ZwJSou-TVo90A, title: [PRISTIN - We Like] KPOP TV Show | M COUNTDOWN 170914 EP.541, description: KPOP Chart Show M COUNTDOWN | EP.541 - PRISTIN - We Like ?Watch more video clips: http://MCOUNTDOWN-KPOP2017 [Kor Ver.] ??? ..., thumbnails: {default: {url: https://i.ytimg.com/vi/e3pUxU_bE6w/default.jpg, width: 120, height: 90}, medium: {url: https://i.ytimg.com/vi/e3pUxU_bE6w/mqdefault.jpg, width: 320, height: 180}, high: {url: https://i.ytimg.com/vi/e3pUxU_bE6w/hqdefault.jpg, width: 480, height: 360}}, channelTitle: Mnet K-POP, liveBroadcastContent: none}}, {kind: youtube#searchResult, etag: "VPWTmrH7dFmi4s1RqrK4tLejnRI/1JCCNBPNbFeusCp_9-pl4i8q5OU", id: {kind: youtube#video, videoId: Cc4hO9RLdl4}, snippet: {publishedAt: 2017-09-14T10:37:29.000Z, channelId: UCbD8EppRX3ZwJSou-TVo90A, title: [EXO - Power] KPOP TV Show | M COUNTDOWN 170914 EP.541, description: KPOP Chart Show M COUNTDOWN | EP.541 - EXO - Power ?Watch more video clips: http://MCOUNTDOWN-KPOP2017 [Kor Ver.] Power Up! '#EXO' ?? ..., thumbnails: {default: {url: https://i.ytimg.com/vi/Cc4hO9RLdl4/default.jpg, width: 120, height: 90}, medium: {url: https://i.ytimg.com/vi/Cc4hO9RLdl4/mqdefault.jpg, width: 320, height: 180}, high: {url: https://i.ytimg.com/vi/Cc4hO9RLdl4/hqdefault.jpg, width: 480, height: 360}}, channelTitle: Mnet K-POP, liveBroadcastContent: none}}, {kind: youtube#searchResult, etag: "VPWTmrH7dFmi4s1RqrK4tLejnRI/ZnYC4e5evyfldkM67HsDuV8Yh3E", id: {kind: youtube#video, videoId: BBcOM25wrVo}, snippet: {publishedAt: 2017-08-18T15:21:48.000Z, channelId: UCtFtO4By4czgkYGvEXvJu0A, title: Kpop Banned Dance: MV vs LIVE, description: Kpop Banned Dance: MV vs LIVE Koreas biggest broadcasting companies has strict rules and standards on what lyrics and dances moves can be performed., thumbnails: {default: {url: https://i.ytimg.com/vi/BBcOM25wrVo/default.jpg, width: 120, height: 90}, medium: {url: https://i.ytimg.com/vi/BBcOM25wrVo/mqdefault.jpg, width: 320, height: 180}, high: {url: https://i.ytimg.com/vi/BBcOM25wrVo/hqdefault.jpg, width: 480, height: 360}}, channelTitle: Kpop Corn, liveBroadcastContent: none}}]}
*** UPDATE WITH FOR LOOP STATEMENT
*** 使用 FOR 循环语句更新
Here is code for my for loopthat's returning a type 'String' is not a subtype of type 'int' of 'index'error...
这是我for loop返回type 'String' is not a subtype of type 'int' of 'index'错误的代码...
Map data = JSON.decode(response);
var videos = data['items'];
for (var items in videos['snippet']){
print(items);
}
Running a loop through items in videosgives me 3 separate entries for the 3 videos I'm looking for - including snippets. Trying to get the individual snippets is failing. Please point me in the right direction.
运行循环items in videos为我正在寻找的 3 个视频提供了 3 个单独的条目 - 包括片段。尝试获取单个片段失败。请指出我正确的方向。
回答by matanlurey
It looks like data['items']is a List(i.e. a JSON Array), not a Map.
它看起来像是data['items']一个List(即一个 JSON 数组),而不是一个Map.
You can use list comprehension methods to help here:
您可以使用列表理解方法来帮助这里:
final items = (data['items'] as List).map((i) => new CardInfo.fromJson(i));
for (final item in items) {
print(item.id);
}
回答by aziza
The following line gives you the Listof items.
下面的线给你List的items。
var videos = data['items'];
and you get the error because of this line
由于这一行,您会收到错误消息
for(var items in videos['snippet'])
In the previous line you think you are iterating on the data inside snippet, while in fact, you are trying to iterate on the index 'snippet' inside the list of videos, which does not make sense because iterating over any list happens using integer values videos[0] , videos [1], videos [2].. while you are passing a String'snippet'
在上一行中,您认为您正在迭代内部的数据snippet,而实际上,您正在尝试对视频列表中的索引“片段”进行迭代,这是没有意义的,因为迭代任何列表都是使用整数值进行的videos[0] , videos [1], videos [2]。 . 当你经过一个String'snippet'
You need first to iterate on your videoslist item by item (each item is a Map). Store each Mapin a variable. then you can access the values of snippetby myMap['snippet']
您首先需要videos逐项迭代您的列表(每个项目都是一个 Map)。将每个存储Map在一个变量中。然后您可以访问snippetby的值myMap['snippet']
Map data = JSON.decode(response);
var videos = data['items']; //returns a List of Maps
for (var items in videos){ //iterate over the list
Map myMap = items; //store each map
print(myMap['snippet']);
}
See if this solves your problem.
看看这是否能解决您的问题。
回答by Harbdollar
I would Love to share this and some expert can also please improve this codes, After alot of hours have battle with it.
我很想分享这个,一些专家也可以改进这个代码,经过很多小时的战斗。
Model Class
模型类
class Testimony{
String fullname;
String testimony;
Testimony({this.fullname,
this.testimony});
factory Testimony.fromJson(Map<String, dynamic> json) => new Testimony(
fullname: json['fullname'] as String,
testimony: json['testimony'] as String,
);
}
API CLASS
API类
List<Testimony> ToListandMap (String responseBody) {
Map data = json.decode(responseBody);
var videos = data['testimonies']; //returns a List of Maps
final casting = videos.cast<Map<String, dynamic>>();
return casting.map<Testimony>((json) => Testimony.fromJson(json)).toList();
}
Future<List<Testimony>> fetchTestimonies(http.Client client) async {
final response = await client.get('https://tryjambcbt.com/api/testimonies');
return ToList(response.body);
}
MainWidget for UI
用于 UI 的 MainWidget
FutureBuilder<List<Testimony>>(
future: fetchTestimonies(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? TestimonyList(testimony: snapshot.data)
: Center(child: CircularProgressIndicator());
},
),
Widget
小工具
class TestimonyList extends StatelessWidget {
final List<Testimony> testimony;
TestimonyList({Key key, this.testimony}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView.builder(
physics: BouncingScrollPhysics(),
padding: EdgeInsets.only(bottom: 10),
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: testimony.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.only(right: 10),
child: Text(testimony[index].testimony)
);
},
);
}
}

