簡體   English   中英

如何從顫振中的 API 獲取 JSON 數據

[英]How to get JSON data from an API in flutter

自從我昨天開始在我的項目中編碼以來,我面臨着同樣的問題,該項目的一部分是從給定的 api 獲取一些 json 數據。

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

我正在研究 flutter SDK,我很困惑為什么它不適合我!我的工作是只獲取鏈接、標題和 source_url 對象,但我無法獲取它。

我在顫振文檔中嘗試了以下代碼
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 響應是List<dynamic>類型,但您正在Map String, dynamic中獲取響應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()
    );
  }
}

在此處輸入圖片說明

你需要改變你的班級。 您需要根據 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 類。 這節省了很多時間。

試試下面的代碼:

factory Post.fromMap(Map<String, dynamic> json) {
  return Post(
    id: json['id'],
    title: json['title'].cast<String>(),
    link: json['link'].cast<String>()
  );
}
**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,
                                            ),
                                          ),
                                        ),
    )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM