自从我昨天开始在我的项目上编码以来,我面临着同样的问题,该项目的一部分是从给定的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();
},
),
),
),
);
}
}
我只有下面的消息:
动态类型列表不是动态映射字符串类型的子类型
任何帮助将不胜感激。
预先感谢。
答案 0 :(得分:1)
您的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()
);
}
}
答案 1 :(得分:0)
尝试以下代码:
factory Post.fromMap(Map<String, dynamic> json) {
return Post(
id: json['id'],
title: json['title'].cast<String>(),
link: json['link'].cast<String>()
);
}
答案 2 :(得分: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类。这样可以节省很多时间。
答案 3 :(得分:-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,
),
),
),
)