Menu
CoddyTech

Leer JSON

Parte de la sección Datos y red del Journey de Flutter de Coddy. Lección 15 de 27.

Los servidores rara vez responden con una oración sencilla. Envían JSON: texto que contiene datos, con nombres entre comillas y valores después de dos puntos. La API de práctica en /user responde así:

{
  "name": "Maya Chen",
  "email": "maya@example.com",
  "age": 28,
  "isPro": true
}

Para tu aplicación, es una sola String larga. jsonDecode, de la biblioteca dart:convert de Dart, convierte ese texto en valores de Dart. Las llaves se convierten en un Map: los nombres son sus claves.

import 'dart:convert';

final Map<String, dynamic> user = jsonDecode(body);
print(user['name']);   // Maya Chen

Las claves siempre son cadenas. Los valores pueden ser texto, números, true o false, listas o más mapas, así que su tipo es dynamic: «cualquier tipo, determinado mientras se ejecuta la aplicación». Las claves deben coincidir exactamente: user['Name'] no es user['name'], y una clave inexistente devuelve null.

Decodifica la respuesta donde la obtienes, en su propia función, para que la pantalla reciba datos listos para usar.

challenge icon

Desafío

Intermedio

La pantalla de perfil muestra el JSON sin procesar. Muestra a la persona:

  • loadUser devuelve un Future<Map<String, dynamic>>: espera fetch('/user') y devuelve jsonDecode del cuerpo (importa dart:convert)
  • _user y FutureBuilder también usan ese tipo
  • cuando llegan los datos, muestra un Column con user['name'] (tamaño 28, en negrita) y debajo user['email']

Pruébalo tú mismo

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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Datos y red

Practica por tu cuenta: Compilador de Flutter online