如何从flutter中的API获取JSON数据

问题描述 投票:0回答:5

自从我昨天开始在我的项目上编码以来,我面临着同样的问题,该项目的一部分是从给定的 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();
            },
          ),
        ),
      ),
    );
  }
}

我只收到以下讯息:
List 类型动态不是 Map String 类型的子类型,动态

任何帮助将不胜感激。
预先感谢。

json flutter http
5个回答
7
投票

您的 JSON 响应类型为

List<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();

  }
}

Bean类

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

enter image description here


0
投票

你需要改变你的班级。您需要根据 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 类。这节省了很多时间。


0
投票

您可以使用 Flutter 中的 http 包向 API 端点发出 HTTP GET 请求,然后使用 dart:convert 库的

jsonDecode
函数解析 JSON 响应。这是一个例子:

import 'package:http/http.dart' as http;
import 'dart:convert';

final response = await http.get(Uri.parse('https://example.com/api/data'));
final jsonData = jsonDecode(response.body);

-1
投票

尝试以下代码:

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

-1
投票
**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,
                                            ),
                                          ),
                                        ),
    )
© www.soinside.com 2019 - 2024. All rights reserved.