Menu
CoddyTech

读取 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。

在获取回复时,在单独的函数中解码它,这样屏幕就能拿到可直接使用的数据。

challenge icon

挑战

中等

个人资料页面显示的是原始 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();
          },
        ),
      ),
    );
  }
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

数据与网络中的所有课

自己练习: Flutter 在线编译器