Danh sách từ JSON
Thuộc phần Dữ liệu và mạng trong hành trình Flutter của Coddy. Bài học 18 trên 27.
Nhiều câu trả lời là danh sách: mọi cuốn sách, mọi tin nhắn, mọi ngày trong dự báo. Trong JSON, danh sách được viết trong dấu ngoặc vuông, và ở đây mỗi phần tử là một đối tượng:
[
{"title": "Frankenstein", "author": "Mary Shelley"},
{"title": "Pride and Prejudice", "author": "Jane Austen"}
]jsonDecode chuyển dấu ngoặc vuông thành một List. Các phần tử của nó cũng có kiểu dynamic, nên hãy nêu kiểu bạn mong đợi bằng as: List<dynamic> cho danh sách, Map<String, dynamic> cho từng phần tử.
Sau đó, chuyển từng phần tử thành một Book bằng map, rồi thu thập kết quả bằng toList():
final items = jsonDecode(body) as List<dynamic>;
return items
.map((item) => Book.fromJson(item as Map<String, dynamic>))
.toList();Chỉ dùng map sẽ tạo ra một Iterable lười, chứ không phải List, nên mới cần toList(). Sau đó, màn hình có một List<Book> để dùng với ListView.builder.
Thử thách
Trung bìnhKệ sách chỉ hiển thị cuốn sách đầu tiên. Hãy sửa loadBooks để chuyển mọi phần tử trong danh sách thành một Book, bằng cách dùng items.map(...) và .toList().
Tự làm thử
import 'dart:convert';
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: BooksScreen(),
);
}
}
class BooksScreen extends StatefulWidget {
const BooksScreen({super.key});
@override
State<BooksScreen> createState() => _BooksScreenState();
}
class _BooksScreenState extends State<BooksScreen> {
late Future<List<Book>> _books;
@override
void initState() {
super.initState();
_books = loadBooks();
}
Future<List<Book>> loadBooks() async {
final body = await fetch('/books');
final items = jsonDecode(body) as List<dynamic>;
return [Book.fromJson(items[0] as Map<String, dynamic>)];
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Books')),
body: FutureBuilder<List<Book>>(
future: _books,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(child: Text('Could not load: ${snapshot.error}'));
}
if (snapshot.hasData) {
final books = snapshot.data!;
return ListView.builder(
itemCount: books.length,
itemBuilder: (context, index) {
final book = books[index];
return ListTile(
title: Text(book.title),
subtitle: Text(book.author),
);
},
);
}
return const Center(child: CircularProgressIndicator());
},
),
);
}
}
class Book {
Book({required this.title, required this.author});
final String title;
final String author;
factory Book.fromJson(Map<String, dynamic> json) {
return Book(
title: json['title'] as String,
author: json['author'] as String,
);
}
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Dữ liệu và mạng
Tự luyện tập: Trình biên dịch Flutter online