Menu
CoddyTech

Eine Liste aus JSON

Teil des Abschnitts Daten und Netzwerk der Flutter-Journey von Coddy. Lektion 18 von 27.

Viele Antworten sind Listen: jedes Buch, jede Nachricht, jeder Tag einer Vorhersage. In JSON wird eine Liste in eckigen Klammern geschrieben, und hier ist jedes Element ein Objekt:

[
  {"title": "Frankenstein", "author": "Mary Shelley"},
  {"title": "Pride and Prejudice", "author": "Jane Austen"}
]

jsonDecode wandelt eckige Klammern in eine List um. Auch ihre Elemente sind dynamic, also gib mit as an, was du erwartest: List<dynamic> für die Liste, Map<String, dynamic> für jedes Element.

Wandle dann jedes Element mit map in ein Book um und sammle die Ergebnisse mit toList():

final items = jsonDecode(body) as List<dynamic>;
return items
    .map((item) => Book.fromJson(item as Map<String, dynamic>))
    .toList();

map allein ergibt ein verzögert ausgewertetes Iterable, keine List, deshalb steht dort toList(). Der Bildschirm verfügt dann über eine List<Book> für ListView.builder.

challenge icon

Aufgabe

Mittel

Das Regal zeigt nur das erste Buch. Sorge dafür, dass loadBooks jedes Element der Liste mit items.map(...) und .toList() in ein Book umwandelt.

Probier es selbst

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,
    );
  }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Daten und Netzwerk

Übe selbstständig: Online-Flutter-Compiler