如何从List中映射Flutter JSON字符串?

时间:2017-09-14 23:25:16

标签: json serialization dart flutter

我已成功将我的回复从我的YouTube JSON网址打印为字符串,但当我尝试序列化"项目"我收到以下错误Unhandled exception: type 'List' is not a subtype of type 'Map' of 'json' where List is from dart:core Map is from dart:core

这是我的代码......

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']正在打印,但print(ci.id)或任何卡片信息变量都会引发上述错误。

**** 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}}]}

***更新LOOP声明

以下是我的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);
    }

通过items in videos运行循环,为我正在寻找的3个视频提供了3个单独的条目 - 包括代码段。试图获取单个代码段失败了。请指出我正确的方向。

3 个答案:

答案 0 :(得分:14)

看起来data['items']List(即JSON数组),而不是Map

您可以使用列表理解方法来帮助:

final items = (data['items'] as List).map((i) => new CardInfo.fromJson(i));
for (final item in items) {
  print(item.id);
}

答案 1 :(得分:1)

以下行为您提供了List的{​​{1}}。

items

因为这行

而出现错误
var videos = data['items'];

在上一行中,您认为正在迭代for(var items in videos['snippet']) 内的数据,而事实上,您正试图在视频列表中迭代索引'片段',这是没有意义的,因为迭代当您传递snippet videos[0] , videos [1], videos [2]

时,使用整数值String ...发生任何列表

首先需要逐项迭代'snippet'列表(每个项目都是Map)。将每个videos存储在变量中。然后,您可以Map

访问snippet的值
myMap['snippet']

看看这是否能解决您的问题。

答案 2 :(得分:0)

我很乐意分享此信息,一些专家也可以改进此代码,经过数小时的努力后,我们会与之抗争。

模型类

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

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);
         }

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());
    },
  ),

小部件

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)
       );
      },
    );
   }
  }