如何在 Flutter 中从 API 获取 JSON 数据
Posted
技术标签:
【中文标题】如何在 Flutter 中从 API 获取 JSON 数据【英文标题】:How to get JSON data from an API in flutter 【发布时间】: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();
,
),
),
),
);
我只得到以下消息:类型列表动态不是映射字符串类型的子类型,动态
任何帮助将不胜感激。 提前致谢。
【问题讨论】:
【参考方案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<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()
);
【讨论】:
我收到 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,
),
),
),
)
【讨论】:
以上是关于如何在 Flutter 中从 API 获取 JSON 数据的主要内容,如果未能解决你的问题,请参考以下文章