Menu
CoddyTech

Konstruktor fromJson

Termasuk bagian Data dan Jaringan dalam perjalanan Flutter di Coddy. Pelajaran 17 dari 27.

Membaca user['name'] as String di semua layar membuat kodemu berantakan, dan satu typo pada key bisa merusaknya. Solusi yang umum adalah menggunakan class untuk data tersebut, dengan satu constructor yang memahami JSON. Constructor ini disebut fromJson:

class User {
  User({required this.name, required this.age});

  final String name;
  final int age;

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      name: json['name'] as String,
      age: json['age'] as int,
    );
  }
}

User.fromJson adalah named constructor, cara kedua untuk membuat User. Kata factory memungkinkan constructor menjalankan kode dan return object yang dibuatnya. Constructor biasa tidak bisa return apa pun.

Sekarang JSON dibaca di satu tempat. Bagian lain dari aplikasi mendapatkan User yang sebenarnya, dengan user.name bertipe String, dan typo akan menjadi compile error, bukan null:

final body = await fetch('/user');
return User.fromJson(jsonDecode(body));

Hampir setiap aplikasi yang berkomunikasi dengan server memiliki fromJson untuk setiap jenis data yang diterimanya.

challenge icon

Tantangan

Sulit

Profil menampilkan Unknown: loadUser mengabaikan JSON. Tambahkan factory User.fromJson(Map<String, dynamic> json) pada User untuk membaca name, email, dan age, lalu buat loadUser mengembalikan User.fromJson(jsonDecode(body)). Impor dart:convert.

Coba sendiri

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<User> _user;

  @override
  void initState() {
    super.initState();
    _user = loadUser();
  }

  Future<User> loadUser() async {
    final body = await fetch('/user');
    print(body);
    return User(name: 'Unknown', email: 'unknown', age: 0);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Profile')),
      body: Center(
        child: FutureBuilder<User>(
          future: _user,
          builder: (context, snapshot) {
            if (snapshot.hasError) {
              return Text('Could not load: ${snapshot.error}');
            }
            if (snapshot.hasData) {
              final user = snapshot.data!;
              return Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text(
                    user.name,
                    style: const TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(height: 8),
                  Text(user.email, style: const TextStyle(fontSize: 18)),
                  const SizedBox(height: 8),
                  Text('${user.age} years old'),
                ],
              );
            }
            return const CircularProgressIndicator();
          },
        ),
      ),
    );
  }
}

class User {
  User({required this.name, required this.email, required this.age});

  final String name;
  final String email;
  final int age;
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Data dan Jaringan

Latihan sendiri: Compiler Flutter online