Reading JSON
Part of the Data and the Network section of Coddy's Flutter journey. Lesson 15 of 27.
Servers rarely answer with a plain sentence. They send JSON: text that holds data, with names in quotes and values after a colon. The practice API's /user answers this:
{
"name": "Maya Chen",
"email": "maya@example.com",
"age": 28,
"isPro": true
}To your app it is one long String. jsonDecode, from Dart's dart:convert library, turns that text into Dart values. Curly braces become a Map: the names are its keys.
import 'dart:convert';
final Map<String, dynamic> user = jsonDecode(body);
print(user['name']); // Maya ChenThe keys are always strings. The values can be text, numbers, true or false, lists or more maps, so their type is dynamic: "any type, decided while the app runs". Keys match exactly: user['Name'] is not user['name'], and a missing key gives null.
Decode the answer where you fetch it, in its own function, so the screen gets ready-to-use data.
Challenge
MediumThe profile screen shows the raw JSON. Show the person instead:
loadUserreturns aFuture<Map<String, dynamic>>: it awaitsfetch('/user')and returnsjsonDecodeof the body (importdart:convert)_userand theFutureBuilderuse that type too- when the data arrives, show a
Columnwithuser['name'](size 28, bold) and under ituser['email']
Try it yourself
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();
},
),
),
);
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Data and the Network
Practice on your own: Online Flutter compiler