读取 JSON
本课属于 Coddy Flutter 学习旅程的“数据与网络”单元。第 15 课,共 27 课。
服务器很少用一句普通的话来回复。它们会发送 JSON:一种包含数据的文本,名称放在引号中,值写在冒号后面。练习用 API 的 /user 会返回以下内容:
{
"name": "Maya Chen",
"email": "maya@example.com",
"age": 28,
"isPro": true
}对你的应用来说,它就是一个很长的 String。Dart 的 dart:convert 库中的 jsonDecode 会把这段文本转换为 Dart 值。花括号会变成一个 Map:名称就是它的键。
import 'dart:convert';
final Map<String, dynamic> user = jsonDecode(body);
print(user['name']); // Maya Chen键始终是字符串。值可以是文本、数字、true 或 false、列表或更多映射,因此它们的类型是 dynamic,意思是“任何类型,由应用在运行时决定”。键必须完全匹配:user['Name'] 不等于 user['name'],而缺少的键会返回 null。
在获取回复时,在单独的函数中解码它,这样屏幕就能拿到可直接使用的数据。
挑战
中等个人资料页面显示的是原始 JSON。改为显示人物信息:
loadUser返回一个Future<Map<String, dynamic>>:它会等待fetch('/user'),并返回对响应正文调用jsonDecode的结果(导入dart:convert)_user和FutureBuilder也使用这种类型- 数据到达后,显示一个
Column,其中包含user['name'](字号为 28,粗体),下方显示user['email']
亲手试试
import 'package:flutter/material.dart';
import 'api.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: ProfileScreen(),
);
}
}
class ProfileScreen extends StatefulWidget {
const ProfileScreen({super.key});
@override
State<ProfileScreen> createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
late Future<String> _user;
@override
void initState() {
super.initState();
_user = loadUser();
}
Future<String> loadUser() async {
return fetch('/user');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Profile')),
body: Center(
child: FutureBuilder<String>(
future: _user,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Could not load: ${snapshot.error}');
}
if (snapshot.hasData) {
return Text(snapshot.data!);
}
return const CircularProgressIndicator();
},
),
),
);
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
数据与网络中的所有课
自己练习: Flutter 在线编译器