颤振类型 'Null' 不是类型"int"的子类型,试图将复杂的 JSON 转换为颤振



这是我的json:https://my-json-server.typicode.com/fluttirci/testJson/db

只有在只有一个json对象的情况下,此代码才有效。但是,对于这个employees json,它不起作用。Flutter的文档对这个主题不是很清楚。它们只在一行json上工作。我想做的是,我想把所有的数据都输入我的手机屏幕。如果我得到了,我会把它们放在桌子或网格上。但它不会起作用。它说类型"Null"不是类型"int"的子类型。这是我的代码:

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<Album> fetchAlbum() async {
final response = await http.get(
Uri.parse('https://my-json-server.typicode.com/fluttirci/testJson/db'));
print(response);
Map<String, dynamic> userMap = jsonDecode(response.body);
if (response.statusCode == 200) {
return Album.fromJson(userMap); //testing
} else {
throw Exception('Failed to load album');
}
}
class Album {
final int userId;
final int id;
final String title;
Album(this.userId, this.id, this.title);
Album.fromJson(Map<String, dynamic> json)
: userId = json['userId'],
id = json['id'],
title = json['title'];
Map<String, dynamic> toJson() => {
'userId': userId,
'id': id,
'title': title,
};
}
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Future<Album> futureAlbum;
late Future<Album> user;
@override
void initState() {
super.initState();
user = fetchAlbum();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder<Album>(
future: user,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data!.title);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
),
),
),
);
}
}

试试这个:

Future<List<Album>> fetchAlbum() async {
final response = await http.get(
Uri.parse('https://my-json-server.typicode.com/fluttirci/testJson/db'));
print(response);
Map<String, dynamic> userMap = jsonDecode(response.body);
if (response.statusCode == 200) {
return (userMap['employees'] as List).map((e) => Album.fromJson(e)).toList()

} else {
throw Exception('Failed to load album');
}
}

然后将您的FutureBuilder更改为:

FutureBuilder<List<Album>>(
future: user,
builder: (context, snapshot) {
if (snapshot.hasData) {
List<Album> data = snapshot.data ?? [];
return ListView.builder(
itemBuilder: (context, index) {
return Column(children: [
Text(data[index].title ?? ""),
]);
},
itemCount: data.length,
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
)

您的response.body在employees键上返回一个列表。并用响应测试该模型

Future<List<Album>?> fetchAlbum() async {
final response = await http.get(
Uri.parse('https://my-json-server.typicode.com/fluttirci/testJson/db'));
if (response.statusCode == 200) {
final data = jsonDecode(response.body)["employees"] as List?;
return data?.map((e) => Album.fromMap(e)).toList();
} else {
throw Exception('Failed to load album');
}
}
class Album {
final int userId;
final int id;
final String title;
Album(this.userId, this.id, this.title);
Map<String, dynamic> toMap() {
final result = <String, dynamic>{};
result.addAll({'userId': userId});
result.addAll({'id': id});
result.addAll({'title': title});
return result;
}
factory Album.fromMap(Map<String, dynamic> map) {
return Album(
map['userId']?.toInt() ?? 0,
map['id']?.toInt() ?? 0,
map['title'] ?? '',
);
}
String toJson() => json.encode(toMap());
factory Album.fromJson(String source) => Album.fromMap(json.decode(source));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late final user = fetchAlbum();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<List<Album>?>(
future: user,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data?.length,
itemBuilder: (context, index) =>
Text("${snapshot.data?[index].title}"),
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
),
),
);
}
}

所以resultMap应该看起来像这样:

{
"employees": [
{
"userId": 1,
"id": 2,
"title": "Doe"
},
{
"userId": 2,
"id": 3,
"title": "Smith"
},
{
"userId": 3,
"id": 4,
"title": "Jones"
}
]
}

这是一个只有一个属性的映射,它将其视为其他映射的List

因此访问json['userId']将尝试从该映射中获取userId,而该映射在中不存在

您需要访问employees属性:

json["employees"]

然后你得到它的值,它是映射的嵌套List,现在你可以用它的索引访问List中的一个元素,然后得到userId:

json["employees"][0]["userId"] // 1
json["employees"][1]["userId"] // 2
json["employees"][2]["userId"] // 3

希望这能给你一个更好的方法来做你想做的事情,以及你需要做的事情。

所以这个:

return Album.fromJson(userMap);

应该用这个来代替,例如:

return Album.fromJson(userMap["employees"][0]);

这里的userMap["employees"][0]是:

{
"userId": 1,
"id": 2,
"title": "Doe"
},

现在它应该从中生成一个CCD_ 11对象

如果要获得List而不是List<Map<string, dynamic>>,则需要使用map方法或for loop迭代整个列表

希望它能帮助

最新更新