【问题标题】:How to get JSON data from an API in flutter如何在 Flutter 中从 API 获取 JSON 数据
【发布时间】:2019-10-16 20:51:29
【问题描述】:

自从我昨天开始对我的项目进行编码以来,我面临着同样的问题,该项目的一部分是从给定的 api 获取一些 json 数据。

我的 api 链接是:http://alkadhum-col.edu.iq/wp-json/wp/v2/posts?_embed

我正在开发flutter SDK,我很困惑为什么它不适合我!我的工作是只获取链接、标题和source_url 对象,但我无法获取它。

我在 Flutter 文档中尝试了以下代码
https://flutter.dev/docs/cookbook/networking/fetch-data 并且根据我的需要进行了一些修改后没有得到任何数据。

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

Future<Post> fetchPost() async {
  final response =
      await http.get('http://alkadhum-col.edu.iq/wp-json/wp/v2/posts/');

  if (response.statusCode == 200) {
    // If the call to the server was successful, parse the JSON
    return Post.fromJson(json.decode(response.body));
  } else {
    // If that call was not successful, throw an error.
    throw Exception('Failed to load post');
  }
}

class Post {

  final int id;
  String title;
  String link;


  Post({this.id, this.title, this.link});

  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      id: json['id'],
      title: json['title'].toString(),
      link: json['link'].toString()
    );
  }
}

void main() => runApp(MyApp(post: fetchPost()));

class MyApp extends StatelessWidget {
  final Future<Post> post;

  MyApp({Key key, this.post}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Fetch Data Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Fetch Data Example'),
        ),
        body: Center(
          child: FutureBuilder<Post>(
            future: post,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(snapshot.data.link);
              } else if (snapshot.hasError) {
                return Text("${snapshot.error}");
              }

              // By default, show a loading spinner
              return CircularProgressIndicator();
            },
          ),
        ),
      ),
    );
  }
}

我只得到以下消息:
类型列表动态不是映射字符串类型的子类型,动态

任何帮助将不胜感激。
提前致谢。

【问题讨论】:

    标签: json api http flutter


    【解决方案1】:

    试试下面的代码:

    factory Post.fromMap(Map<String, dynamic> json) {
      return Post(
        id: json['id'],
        title: json['title'].cast<String>(),
        link: json['link'].cast<String>()
      );
    }
    

    【讨论】:

      【解决方案2】:

      您的 JSON 响应的类型为 List&lt;dynamic&gt;,但您正在接受 Map String, dynamic 的响应,但您可以执行类似的操作

           import 'dart:async';
      import 'dart:convert';
      import 'package:flutter/material.dart';
      import 'package:clickmeetplay/iam/user/postbean.dart';
      import 'package:http/http.dart' as http;
      
      class PostHome extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return MaterialApp(home: Scaffold(body: PostScreen(),),);
        }
      }
      
      class PostScreen extends StatefulWidget {
        @override
        _PostScreenState createState() => _PostScreenState();
      }
      
      class _PostScreenState extends State<PostScreen> {
      
        List<Post> _postList =new List<Post>();
      
        Future<List<Post> > fetchPost() async {
          final response =
          await http.get('http://alkadhum-col.edu.iq/wp-json/wp/v2/posts/');
      
          if (response.statusCode == 200) {
            // If the call to the server was successful, parse the JSON
            List<dynamic> values=new List<dynamic>();
            values = json.decode(response.body);
            if(values.length>0){
              for(int i=0;i<values.length;i++){
                if(values[i]!=null){
                  Map<String,dynamic> map=values[i];
                  _postList .add(Post.fromJson(map));
                  debugPrint('Id-------${map['id']}');
                }
              }
            }
            return _postList;
      
          } else {
            // If that call was not successful, throw an error.
            throw Exception('Failed to load post');
          }
        }
        @override
        Widget build(BuildContext context) {
          return Container();
        }
      
        @override
        void initState() {
      
          fetchPost();
      
        }
      }
      

      豆类

      class Post {
      
        final int id;
        String title;
        String link;
      
      
        Post({this.id, this.title, this.link});
      
        factory Post.fromJson(Map<String, dynamic> json) {
          return Post(
              id: json['id'],
              title: json['title'].toString(),
              link: json['link'].toString()
          );
        }
      }
      

      【讨论】:

      • 我收到 14 个错误,这对我不起作用,名称 Post 不是类型,它不能用作类型参数。这是错误之一。
      • 在 main 函数中添加 PostHome 到 runApp,现在运行良好。
      • 我怎样才能在屏幕上打印它们而不仅仅是在控制台中?
      • 你必须在你的视图中使用 listview。
      • 怎么用?
      【解决方案3】:

      你需要改变你的班级。您需要根据 JSON 响应创建您的类结构。

      class Post {
        int id;
        String title;
        String link;
      
        Post({this.id, this.title, this.link});
      
        factory Post.fromJson(Map<String, dynamic> json) {
           return Post(
               id: json['id'],
               title: title = json['title'] != null ? new Title.fromJson(json['title']) : null;
               link: json['link'].toString()
              );
          }
       }
      
      
      class Title {
          String rendered;
      
          Title({this.rendered});
      
           Title.fromJson(Map<String, dynamic> json) {
                rendered = json['rendered'];
            }
      
             Map<String, dynamic> toJson() {
                final Map<String, dynamic> data = new Map<String, dynamic>();
                data['rendered'] = this.rendered;
                return data;
              }
        }
      

      然后,在您的 API 方法中。作为响应,您得到的是一个 JSON 数组。所以,把它放在一个列表中,并将响应转换为你的 JSON 类。

      Future<List<Post>> fetchPost() async {
        final response =
              await http.get('http://alkadhum-col.edu.iq/wp-json/wp/v2/posts/');
      
           if (response.statusCode == 200) {
             // If the call to the server was successful, parse the JSON
              var lst = response.body as List;
              return lst.map((d) => Post.fromJson(d)).toList();
            } else {
              // If that call was not successful, throw an error.
                throw Exception('Failed to load post');
            }
       }
      

      您始终可以使用 https://javiercbk.github.io/json_to_dart/ 之类的工具从复杂的 JSON 创建 Dart 类。这样可以节省很多时间。

      【讨论】:

        【解决方案4】:
        **Create Api Class**
        
            class ApiUtils {
              static String baseUrl = "http://example/";
            }
        
        **Create Model**
        
            class EventModel {
              String title;
            
              EventModel({this.title});
            
              EventModel.fromJson(Map<String, dynamic> json) {
                title = json['Title'] ?? "";
              
              }
            }
        
        **Create Service**
        
            import 'package:http/http.dart' as http;
            import 'package:NoticeModel.dart';
            import 'dart:convert';
            
            class NoticeService {
              bool error = false;
              bool loading = true;
              var notice;
              bool noticeDetailserror = false;
              bool noticeetailsloading = true;
            
              Future<void> getNotice(dynamic input) async {
                try {
                  noticeDetailserror = false;
            
                  http.Response response = await http.post(ApiUtils.noticeApi,
                      body: input, headers: {'Content-type': 'application/json'});
            
                  Map data = jsonDecode(response.body);
                  if (data["Status"] == true) {
                    notice = data["Data"];
                    notice = notice.map((_data) {
                      return new NoticeModel.fromJson(_data);
                    }).toList();
                    print(notice);
                    noticeetailsloading = false;
                  } else {
                    throw data;
                  }
                } catch (e) {
                  print(e);
                  noticeetailsloading = false;
                  noticeDetailserror = true;
                }
              }
            }
        
        **Main Page**
        
         
        
            var body =
                  json.encode({"IsActive": true, "IsDelete": false, "CompanyId": 18});
              List<dynamic> data;
              var count = 0;
              bool loading = true;
              bool error = false;
            
              void getNoticeDetails() async {
                setState(() {
                  error = false;
                  loading = true;
                });
            
                // SharedPreferences prefs = await SharedPreferences.getInstance();
            
                NoticeService instance = NoticeService();
                await instance.getNotice(body);
                data = instance.notice;
                if (instance.noticeDetailserror == false) {
                  setState(() {
                    count = data.length;
                    loading = false;
                  });
                } else {
                  setState(() {
                    loading = false;
                    error = true;
                  });
            
                  Toast.show("Error Getting Data", context,
                      duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
                }
              }
            
              @override
              void initState() {
                super.initState();
                getNoticeDetails();
              }
            
            body: loading == true
                      ? LinearProgressIndicator()
                      : error == true
                          ? RetryWidget(
                              onRetry: getNoticeDetails,
                            )
                          : SafeArea(
            SizedBox(
                                              width: 270,
                                                  child: Text(
                                                    data[index].title ?? "",
                                                    maxLines: 1,
                                                    overflow: TextOverflow.ellipsis,
                                                    style: TextStyle(
                                                      fontSize: 18,
                                                      color: Colors.grey,
                                                      fontWeight: FontWeight.bold,
                                                    ),
                                                  ),
                                                ),
            )
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-12-24
          • 2021-02-03
          • 2022-01-04
          • 2021-04-11
          • 2020-08-17
          • 2021-07-20
          • 2021-06-27
          相关资源
          最近更新 更多