Obtener datos de internet
Obtener datos a través de internet usando el paquete http.
La mayoría de las aplicaciones requieren algún tipo de comunicación o recuperación de datos de internet. Muchas aplicaciones lo hacen a través de solicitudes HTTP, que se envían desde un cliente a un servidor para realizar una acción específica para un recurso identificado a través de un URI (Uniform Resource Identifier).
Técnicamente, los datos comunicados a través de HTTP pueden tener cualquier formato, pero usar JSON (JavaScript Object Notation) es una opción popular debido a su legibilidad para los humanos y su naturaleza independiente del lenguaje. El Dart SDK y su ecosistema también cuentan con un amplio soporte para JSON con múltiples opciones para satisfacer de la mejor manera los requisitos de tu aplicación.
En este tutorial,
aprenderás más sobre solicitudes HTTP, URIs y JSON.
Luego aprenderás cómo usar package:http
así como el soporte JSON de Dart en la librería dart:convert
para obtener, decodificar y luego usar datos en formato JSON
recuperados de un servidor HTTP.
Conceptos de trasfondo
#Las siguientes secciones proporcionan un trasfondo e información adicionales sobre las tecnologías y conceptos utilizados en el tutorial para facilitar la obtención de datos del servidor. Para saltar directamente al contenido del tutorial, consulta Recuperar las dependencias necesarias.
JSON
#JSON (JavaScript Object Notation) es un formato de intercambio de datos que se ha vuelto omnipresente en el desarrollo de aplicaciones y la comunicación cliente-servidor. Es ligero pero también fácil de leer y escribir para los humanos debido a que está basado en texto. Con JSON, varios tipos de datos y estructuras de datos simples como listas y mapas se pueden serializar y representar mediante strings.
La mayoría de los lenguajes tienen muchas implementaciones y los analizadores se han vuelto extremadamente rápidos, por lo que no necesitas preocuparte por la interoperabilidad o el rendimiento. Para obtener más información sobre el formato JSON, consulta Introducción a JSON. Para aprender más sobre cómo trabajar con JSON en Dart, consulta la guía Uso de JSON.
Solicitudes HTTP
#HTTP (Hypertext Transfer Protocol) es un protocolo sin estado
diseñado para transmitir documentos,
originalmente entre clientes web y servidores web.
Interactuaste con el protocolo para cargar esta página,
ya que tu navegador utiliza una solicitud HTTP GET
para recuperar el contenido de una página de un servidor web.
Desde su introducción, el uso del protocolo HTTP y sus diversas versiones
se ha expandido también a aplicaciones fuera de la web,
básicamente dondequiera que se necesite comunicación de un cliente a un servidor.
Las solicitudes HTTP enviadas desde el cliente para comunicarse con el servidor
están compuestas por múltiples componentes.
Las librerías HTTP, como package:http, te permiten
especificar los siguientes tipos de comunicación:
- Un método HTTP que define la acción deseada,
como
GETpara recuperar datos oPOSTpara enviar nuevos datos. - La ubicación del recurso a través de un URI.
- La versión de HTTP que se está utilizando.
- Cabeceras que proporcionan información adicional al servidor.
- Un cuerpo opcional, para que la solicitud pueda enviar datos al servidor, no solo recuperarlos.
Para aprender más sobre el protocolo HTTP, consulta Una descripción general de HTTP en mdn web docs.
URIs y URLs
#Para hacer una solicitud HTTP, necesitas proporcionar un URI (Uniform Resource Identifier) al recurso. Un URI es una cadena de caracteres que identifica de manera única un recurso. Una URL (Uniform Resource Locator) es un tipo específico de URI que también proporciona la ubicación del recurso. Las URLs de los recursos en la web contienen tres elementos de información. Para esta página actual, la URL está compuesta por:
- El esquema utilizado para determinar el protocolo utilizado:
https - La autoridad o nombre de host del servidor:
dart.dev - La ruta al recurso:
/server/fetch-data.html
También hay otros parámetros opcionales que no son utilizados por la página actual:
- Parámetros para personalizar comportamiento adicional:
?key1=value1&key2=value2 - Un ancla, que no se envía al servidor,
la cual apunta a una ubicación específica en el recurso:
#uris
Para aprender más sobre las URLs, consulta ¿Qué es una URL? en mdn web docs.
Recuperar las dependencias necesarias
#La librería package:http proporciona una solución multiplataforma
para realizar solicitudes HTTP componibles,
con un control detallado opcional.
Para agregar una dependencia de package:http,
ejecuta el siguiente comando dart pub add
desde la raíz de tu repositorio:
dart pub add http
Para usar package:http en tu código,
impórtalo y, opcionalmente, especifica un prefijo de librería:
import 'package:http/http.dart' as http;
Para aprender más detalles sobre package:http,
consulta su página en el sitio pub.dev
y su documentación de la API.
Construir una URL
#Como se mencionó anteriormente, para hacer una solicitud HTTP, primero necesitas una URL que identifique el recurso solicitado o el endpoint al que se accede.
En Dart, las URLs se representan mediante objetos Uri.
Hay muchas formas de construir un Uri,
pero debido a su flexibilidad,
analizar una cadena con Uri.parse para
crear uno es una solución común.
El siguiente snippet muestra dos formas
de crear un objeto Uri
que apunta a información simulada en formato JSON
sobre package:http alojado en este sitio:
// Parse the entire URI, including the scheme
Uri.parse('https://dart.dev/f/packages/http.json');
// Specifically create a URI with the https scheme
Uri.https('dart.dev', '/f/packages/http.json');
Para aprender sobre otras formas de construir e interactuar con URIs,
consulta la documentación de URI.
Hacer una solicitud de red
#Si solo necesitas obtener rápidamente una representación en cadena (string)
de un recurso solicitado,
puedes usar la función de nivel superior read
que se encuentra en package:http
que devuelve un Future<String> o lanza
una ClientException
si la solicitud no fue exitosa.
El siguiente ejemplo utiliza read para
recuperar la información simulada en formato JSON
sobre package:http como un string,
y luego la imprime:
void main() async {
final httpPackageUrl = Uri.https('dart.dev', '/f/packages/http.json');
final httpPackageInfo = await http.read(httpPackageUrl);
print(httpPackageInfo);
}
Esto produce la siguiente salida en formato JSON,
que también se puede ver en tu navegador en
/f/packages/http.json.
{
"name": "http",
"latestVersion": "1.1.2",
"description": "A composable, multi-platform, Future-based API for HTTP requests.",
"publisher": "dart.dev",
"repository": "https://github.com/dart-lang/http"
}
Ten en cuenta la estructura de los datos (en este caso un mapa), ya que la necesitarás al decodificar el JSON más adelante.
Si necesitas otra información de la respuesta,
como el código de estado
o las cabeceras,
puedes usar en su lugar la función de nivel superior get
que devuelve un Future con una Response.
El siguiente snippet utiliza get para obtener la respuesta completa
con el fin de salir temprano si la solicitud no fue exitosa,
lo cual se indica con un código de estado de 200:
void main() async {
final httpPackageUrl = Uri.https('dart.dev', '/f/packages/http.json');
final httpPackageResponse = await http.get(httpPackageUrl);
if (httpPackageResponse.statusCode != 200) {
print('Failed to retrieve the http package!');
return;
}
print(httpPackageResponse.body);
}
Hay muchos otros códigos de estado además del 200 y es posible que tu aplicación quiera manejarlos de manera diferente. Para obtener más información sobre lo que significan los diferentes códigos de estado, consulta Códigos de estado de respuesta HTTP en mdn web docs.
Algunas solicitudes al servidor requieren más información,
como información de autenticación o de agente de usuario (user-agent);
en este caso es posible que debas incluir cabeceras HTTP.
Puedes especificar las cabeceras pasando un Map<String, String>
de los pares clave-valor como el parámetro opcional nombrado headers:
await http.get(
Uri.https('dart.dev', '/f/packages/http.json'),
headers: {'User-Agent': '<product name>/<product-version>'},
);
Hacer múltiples solicitudes
#Si estás realizando múltiples solicitudes al mismo servidor,
puedes en su lugar mantener una conexión persistente
a través de un Client,
el cual tiene métodos similares a los de nivel superior.
Solo asegúrate de limpiar los recursos con
el método close cuando hayas terminado:
void main() async {
final httpPackageUrl = Uri.https('dart.dev', '/f/packages/http.json');
final client = http.Client();
try {
final httpPackageInfo = await client.read(httpPackageUrl);
print(httpPackageInfo);
} finally {
client.close();
}
}
Para permitir que el cliente vuelva a intentar las solicitudes fallidas,
importa package:http/retry.dart y
envuelve tu Client creado en un RetryClient:
import 'package:http/http.dart' as http;
import 'package:http/retry.dart';
void main() async {
final httpPackageUrl = Uri.https('dart.dev', '/f/packages/http.json');
final client = RetryClient(http.Client());
try {
final httpPackageInfo = await client.read(httpPackageUrl);
print(httpPackageInfo);
} finally {
client.close();
}
}
El RetryClient tiene un comportamiento predeterminado para la cantidad
de veces que debe reintentar y cuánto tiempo esperar entre cada solicitud,
pero su comportamiento se puede modificar mediante parámetros
en los constructores RetryClient()
o RetryClient.withDelays().
package:http tiene mucha más funcionalidad y personalización,
así que asegúrate de revisar su página en el sitio pub.dev
y su documentación de la API.
Decodificar los datos recuperados
#Aunque ahora has realizado una solicitud de red y has recuperado los datos devueltos como un string, acceder a partes específicas de información desde un string puede ser un desafío.
Dado que los datos ya están en formato JSON,
puedes usar la función integrada de Dart json.decode
en la librería dart:convert
para convertir la cadena de texto cruda en
una representación JSON utilizando objetos Dart.
En este caso, los datos JSON se representan en una estructura de mapa
y, en JSON, las claves del mapa siempre son strings,
por lo que puedes convertir el resultado de json.decode en un Map<String, dynamic>:
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() async {
final httpPackageUrl = Uri.https('dart.dev', '/f/packages/http.json');
final httpPackageInfo = await http.read(httpPackageUrl);
final httpPackageJson = json.decode(httpPackageInfo) as Map<String, dynamic>;
print(httpPackageJson);
}
Crear una clase estructurada para almacenar los datos
#Para proporcionar al JSON decodificado una mayor estructura, haciendo que sea más fácil trabajar con él, crea una clase que pueda almacenar los datos recuperados usando tipos específicos según el esquema de tus datos.
El siguiente snippet muestra una representación basada en clases
que puede almacenar la información del paquete devuelta
desde el archivo JSON simulado que solicitaste.
Esta estructura asume que todos los campos excepto repository
son obligatorios y se proporcionan siempre.
class PackageInfo {
final String name;
final String latestVersion;
final String description;
final String publisher;
final Uri? repository;
PackageInfo({
required this.name,
required this.latestVersion,
required this.description,
required this.publisher,
this.repository,
});
}
Codificar los datos en tu clase
#Ahora que tienes una clase para almacenar tus datos,
necesitas agregar un mecanismo para convertir
el JSON decodificado en un objeto PackageInfo.
Convierte el JSON decodificado
escribiendo manualmente un método fromJson
que coincida con el formato JSON anterior,
realizando las conversiones de tipo según sea necesario
y manejando el campo opcional repository:
class PackageInfo {
// ···
factory PackageInfo.fromJson(Map<String, dynamic> json) {
final repository = json['repository'] as String?;
return PackageInfo(
name: json['name'] as String,
latestVersion: json['latestVersion'] as String,
description: json['description'] as String,
publisher: json['publisher'] as String,
repository: repository != null ? Uri.tryParse(repository) : null,
);
}
}
Un método escrito a mano, como en el ejemplo anterior, suele ser suficiente para estructuras JSON relativamente simples, pero también existen opciones más flexibles. Para aprender más sobre la serialización y deserialización de JSON, incluyendo la generación automática de la lógica de conversión, consulta la guía Uso de JSON.
Convertir la respuesta a un objeto de tu clase estructurada
#Ahora tienes una clase para almacenar tus datos y una forma de convertir el objeto JSON decodificado en un objeto de ese tipo. A continuación, puedes escribir una función que lo una todo:
- Crea tu
URIbasándote en el nombre de paquete pasado. - Usa
http.getpara recuperar los datos de ese paquete. - Si la solicitud no tiene éxito, lanza una
Exceptiono preferiblemente tu propia subclase personalizada deException. - Si la solicitud tiene éxito, usa
json.decodepara decodificar el cuerpo de la respuesta en una cadena JSON. - Convierte la cadena JSON decodificada en un objeto
PackageInfousando el constructor de fábricaPackageInfo.fromJsonque creaste.
Future<PackageInfo> getPackage(String packageName) async {
final packageUrl = Uri.https('dart.dev', '/f/packages/$packageName.json');
final packageResponse = await http.get(packageUrl);
// If the request didn't succeed, throw an exception
if (packageResponse.statusCode != 200) {
throw PackageRetrievalException(
packageName: packageName,
statusCode: packageResponse.statusCode,
);
}
final packageJson = json.decode(packageResponse.body) as Map<String, dynamic>;
return PackageInfo.fromJson(packageJson);
}
class PackageRetrievalException implements Exception {
final String packageName;
final int? statusCode;
PackageRetrievalException({required this.packageName, this.statusCode});
}
Utilizar los datos convertidos
#Ahora que has recuperado los datos y los has convertido a un formato más accesible, puedes usarlos como quieras. Algunas posibilidades incluyen mostrar la información en una CLI, o mostrarla en una aplicación web o de Flutter.
Aquí tienes un ejemplo completo y ejecutable
que solicita, decodifica y luego muestra
la información simulada sobre los paquetes http y path:
¿Qué sigue?
#Ahora que has recuperado, analizado y utilizado datos de internet, considera aprender más sobre Concurrencia en Dart. Si tus datos son grandes y complejos, puedes mover la recuperación y decodificación a otro isolate como un trabajador en segundo plano para evitar que tu interfaz deje de responder.
A menos que se indique lo contrario, la documentación de este sitio refleja Dart 3.12.2. Página actualizada por última vez el 02-02-2026. Ver fuente oreportar un problema.