Trabaja con datos JSON
Aprende sobre la deserialización JSON en Dart, incluyendo cómo usar `dart:convert`, `jsonDecode` y pattern matching para trabajar con datos JSON de la API de Wikipedia.
En este capítulo, aprenderás a trabajar con datos
JSON (JavaScript Object Notation) en Dart.
JSON es un formato común para el intercambio de datos en la web, y
a menudo te encontrarás con él al trabajar con APIs.
Aprenderás a convertir datos JSON en objetos Dart,
lo que facilitará el trabajo con ellos en tu aplicación.
Usarás la librería dart:convert,
la función jsonDecode y pattern matching.
Qué lograrás
Prerrequisitos
#Antes de comenzar este capítulo, asegúrate de:
- Haber completado el Capítulo 8 y tener un
entorno de desarrollo de Dart en funcionamiento con el proyecto
dartpedia. - Entender la sintaxis básica de Dart, incluyendo clases y tipos de datos.
Tareas
#En este capítulo, crearás clases Dart para representar los datos JSON devueltos por la API de Wikipedia. Esto te permitirá acceder y usar fácilmente los datos en tu aplicación.
Tarea 1: Crear el paquete Wikipedia
#Primero, crea un nuevo paquete Dart para albergar los modelos de datos.
Navega al directorio raíz de tu proyecto (
/dartpedia).-
Ejecuta el siguiente comando en tu terminal:
bashdart create wikipediaEste comando crea un nuevo directorio llamado
wikipediacon la estructura básica de un paquete Dart. Ahora deberías ver una nueva carpetawikipediaen la raíz de tu proyecto, junto concliycommand_runner.
Tarea 2: Configurar un espacio de trabajo de Dart
#Los workspaces de Dart te permiten gestionar múltiples paquetes relacionados dentro de un solo proyecto, simplificando la gestión de dependencias y el desarrollo local. Ahora que estás agregando tu tercer paquete, es un buen momento para configurar tu proyecto para usar un workspace de Dart.
-
Create the root
pubspec.yamlfile.Navega al directorio raíz de tu proyecto (
/dartpedia) y crea un nuevo archivo llamadopubspec.yamlcon el siguiente contenido:yamlname: _ publish_to: none environment: sdk: ^3.8.1 # IMPORTANT: Adjust this to match your Dart SDK version or a compatible range workspace: - cli - command_runner - wikipedia -
Añadir resolución de workspace a los subpaquetes.
Para cada uno de tus subpaquetes (
cli,command_runnerywikipedia), abre sus respectivos archivospubspec.yamly añaderesolution: workspaceapubspec.yaml. Esto le indica a Dart que resuelva las dependencias dentro del workspace.Para
cli/pubspec.yaml:yaml# ... (existing content) ... name: cli description: A sample command-line application. version: 1.0.0 resolution: workspace # Add this line # ... (existing content) ...Para
command_runner/pubspec.yaml:yaml# ... (existing content) ... name: command_runner description: A starting point for Dart libraries or applications. version: 1.0.0 resolution: workspace # Add this line # ... (existing content) ...Para
wikipedia/pubspec.yaml:yaml# ... (existing content) ... name: wikipedia description: A sample command-line application. version: 1.0.0 resolution: workspace # Add this line # ... (existing content) ...
Tarea 3: Crear la clase Summary
#La API de Wikipedia devuelve un objeto JSON que contiene un resumen de un artículo. Creemos una clase Dart para representar este resumen.
-
Crea el directorio
wikipedia/lib/src/model.bashmkdir -p wikipedia/lib/src/model Crea el archivo
wikipedia/lib/src/model/summary.dart.-
Agrega el siguiente código a
wikipedia/lib/src/model/summary.dart:wikipedia/lib/src/model/summary.dartdartimport 'title_set.dart'; class Summary { /// Returns a new [Summary] instance. Summary({ required this.titles, required this.pageid, required this.extract, required this.extractHtml, required this.lang, required this.dir, this.url, this.description, }); /// TitlesSet titles; /// The page ID int pageid; /// First several sentences of an article in plain text String extract; /// First several sentences of an article in simple HTML format String extractHtml; /// Url to the article on Wikipedia String? url; /// The page language code String lang; /// The page language direction code String dir; /// Wikidata description for the page String? description; /// Returns a new [Summary] instance static Summary fromJson(Map<String, Object?> json) { return switch (json) { { 'titles': final Map<String, Object?> titles, 'pageid': final int pageid, 'extract': final String extract, 'extract_html': final String extractHtml, 'lang': final String lang, 'dir': final String dir, 'content_urls': { 'desktop': {'page': final String url}, 'mobile': {'page': String _}, }, 'description': final String description, } => Summary( titles: TitlesSet.fromJson(titles), pageid: pageid, extract: extract, extractHtml: extractHtml, lang: lang, dir: dir, url: url, description: description, ), { 'titles': final Map<String, Object?> titles, 'pageid': final int pageid, 'extract': final String extract, 'extract_html': final String extractHtml, 'lang': final String lang, 'dir': final String dir, 'content_urls': { 'desktop': {'page': final String url}, 'mobile': {'page': String _}, }, } => Summary( titles: TitlesSet.fromJson(titles), pageid: pageid, extract: extract, extractHtml: extractHtml, lang: lang, dir: dir, url: url, ), _ => throw FormatException('Could not deserialize Summary, json=$json'), }; } @override String toString() => 'Summary[' 'titles=$titles, ' 'pageid=$pageid, ' 'extract=$extract, ' 'extractHtml=$extractHtml, ' 'lang=$lang, ' 'dir=$dir, ' 'description=$description' ']'; }Este código define una clase
Summarycon propiedades que corresponden a los campos en la respuesta JSON de la API de Wikipedia. El métodofromJsonutiliza pattern matching para extraer los datos del objeto JSON y crear una nueva instancia deSummary. El métodotoStringproporciona una forma conveniente de imprimir el contenido del objetoSummary. Ten en cuenta que la claseTitlesSetse utiliza en la claseSummary, por lo que necesitarás crearla a continuación.
Tarea 4: Crear la clase TitleSet
#La clase Summary utiliza una clase TitlesSet para representar la información del título.
Creemos esa clase ahora.
Crea el archivo
wikipedia/lib/src/model/title_set.dart.-
Agrega el siguiente código a
wikipedia/lib/src/model/title_set.dart:wikipedia/lib/src/model/title_set.dartdartclass TitlesSet { /// Returns a new [TitlesSet] instance. TitlesSet({ required this.canonical, required this.normalized, required this.display, }); /// the DB key (non-prefixed), e.g. may have _ instead of spaces, /// best for making request URIs, still requires Percent-encoding String canonical; /// the normalized title (https://www.mediawiki.org/wiki/API:Query#Example_2:_Title_normalization), /// e.g. may have spaces instead of _ String normalized; /// the title as it should be displayed to the user String display; /// Returns a new [TitlesSet] instance and imports its values from a JSON map static TitlesSet fromJson(Map<String, Object?> json) { if (json case { 'canonical': final String canonical, 'normalized': final String normalized, 'display': final String display, }) { return TitlesSet( canonical: canonical, normalized: normalized, display: display, ); } throw FormatException('Could not deserialize TitleSet, json=$json'); } @override String toString() => 'TitlesSet[' 'canonical=$canonical, ' 'normalized=$normalized, ' 'display=$display' ']'; }Este código define una clase
TitlesSetcon propiedades que corresponden a la información del título en la respuesta JSON de la API de Wikipedia. El métodofromJsonutiliza pattern matching para extraer los datos del objeto JSON y crear una nueva instancia deTitlesSet. El métodotoStringproporciona una forma conveniente de imprimir el contenido del objetoTitlesSet.
Tarea 5: Crear la clase Article
#La API de Wikipedia también devuelve una lista de artículos en un resultado de búsqueda. Creemos una clase Dart para representar un artículo.
Crea el archivo
wikipedia/lib/src/model/article.dart.-
Agrega el siguiente código a
wikipedia/lib/src/model/article.dart:wikipedia/lib/src/model/article.dartdartclass Article { Article({required this.title, required this.extract}); final String title; final String extract; static List<Article> listFromJson(Map<String, Object?> json) { final List<Article> articles = <Article>[]; if (json case {'query': {'pages': final Map<String, Object?> pages}}) { for (final MapEntry<String, Object?>(:Object? value) in pages.entries) { if (value case { 'title': final String title, 'extract': final String extract, }) { articles.add(Article(title: title, extract: extract)); } } return articles; } throw FormatException('Could not deserialize Article, json=$json'); } Map<String, Object?> toJson() => <String, Object?>{ 'title': title, 'extract': extract, }; @override String toString() { return 'Article{title: $title, extract: $extract}'; } }Este código define una clase
Articlecon propiedades para el título y el extracto de un artículo. El métodolistFromJsonutiliza pattern matching para extraer los datos del objeto JSON y crear una lista de instancias deArticle. El métodotoJsonconvierte el objetoArticlede nuevo en un objeto JSON. El métodotoStringproporciona una forma conveniente de imprimir el contenido del objetoArticle.
Tarea 6: Crear la clase SearchResults
#Finalmente, creamos una clase para representar los resultados de búsqueda de la API de Wikipedia.
Crea el archivo
wikipedia/lib/src/model/search_results.dart.-
Agrega el siguiente código a
wikipedia/lib/src/model/search_results.dart:wikipedia/lib/src/model/search_results.dartdartclass SearchResult { SearchResult({required this.title, required this.url}); final String title; final String url; } class SearchResults { SearchResults(this.results, {this.searchTerm}); final List<SearchResult> results; final String? searchTerm; static SearchResults fromJson(List<Object?> json) { final List<SearchResult> results = <SearchResult>[]; if (json case [ String searchTerm, Iterable articleTitles, Iterable _, Iterable urls, ]) { final List titlesList = articleTitles.toList(); final List urlList = urls.toList(); for (int i = 0; i < articleTitles.length; i++) { results.add(SearchResult(title: titlesList[i], url: urlList[i])); } return SearchResults(results, searchTerm: searchTerm); } throw FormatException('Could not deserialize SearchResults, json=$json'); } @override String toString() { final StringBuffer pretty = StringBuffer(); for (final SearchResult result in results) { pretty.write('${result.url} \n'); } return '\nSearchResults for $searchTerm: \n$pretty'; } }Este código define una clase
SearchResultscon una lista de objetosSearchResulty un término de búsqueda. El métodofromJsonutiliza pattern matching para extraer los datos del objeto JSON y crear una nueva instancia deSearchResults. El métodotoStringproporciona una forma conveniente de imprimir el contenido del objetoSearchResults.
En este punto, has creado modelos de datos para representar estructuras JSON. No hay nada que probar en este punto. Agregarás la lógica de la aplicación en las próximas secciones, lo que te permitirá probar cómo se deserializan los datos de la API de Wikipedia.
Revisión
#Qué lograste
Aquí tienes un resumen de lo que construiste y aprendiste en esta lección.Creaste clases de modelos de datos para JSON
Construiste las clases Summary, TitlesSet, Article y SearchResults
para representar las respuestas de la API de Wikipedia. Estos modelos tipados proporcionan seguridad en tiempo de compilación y soporte de IDE al trabajar con datos de la API.
Usaste dart:convert para trabajar con datos JSON
Importaste la librería dart:convert y usaste jsonDecode() para analizar (parsear) cadenas JSON en objetos Dart, incluyendo
Map y List, con los que luego puedes trabajar programáticamente.
Usaste pattern matching para extraer datos de objetos JSON
Implementaste métodos factory fromJson usando el pattern matching de Dart con expresiones switch
y la sentencia if case. Esta estructura te permitió validar la estructura JSON y extraer valores de los objetos JSON en expresiones únicas y legibles.
Configuraste un workspace de pub
Para simplificar la gestión de dependencias en tu proyecto multipaquete, creaste un nuevo workspace de pub. Para hacerlo, creaste un archivo
pubspec.yaml raíz con una sección workspace: que lista tus paquetes, luego agregaste
resolution: workspace a cada subpaquete.
Cuestionario
#Pon a prueba tu comprensión
1 / 3Un lenguaje de programación diseñado específicamente para el desarrollo web.
No exactamente.
JSON no es un lenguaje de programación. No puedes escribir lógica ni ejecutar código con JSON.
Una librería específica de Dart para manejar la serialización de datos.
No exactamente.
JSON no es específico de Dart ni es una librería. Existió antes que Dart y se usa en todas partes.
Un formato de base de datos utilizado exclusivamente por aplicaciones de JavaScript.
No exactamente.
JSON no es un formato de base de datos, y no es exclusivo de JavaScript. Aunque se originó a partir de la sintaxis de JavaScript, se utiliza en muchos lenguajes y plataformas.
Un formato ligero de intercambio de datos que es fácil de leer y escribir para los humanos y fácil de parsear y generar para las máquinas.
¡Correcto!
JSON (JavaScript Object Notation) es un formato basado en texto para representar datos estructurados. Se usa ampliamente para el intercambio de datos entre aplicaciones, especialmente en APIs web.
jsonDecode parses a JSON object like {"name": "Dart"}, what Dart type does it return?Un
List<String>que contiene los pares clave-valor.No exactamente.
Una lista perdería la relación clave-valor. Los objetos JSON tienen propiedades con nombre, lo que requiere una estructura de datos diferente a una lista.
Un
Stringque contiene el texto JSON.No exactamente.
jsonDecodeanaliza (parsea) la cadena JSON en objetos Dart. Convierte la representación en cadena a datos estructurados, incluyendo mapas y listas, sin mantenerla como una cadena.Una clase
JsonObjectpersonalizada dedart:convert.No exactamente.
No existe una clase
JsonObjecten Dart.jsonDecodedevuelve tipos de colecciones estándar de Dart.Un
Map<String, dynamic>que representa al objeto JSON.¡Correcto!
Los objetos JSON se convierten en
Map<String, dynamic>, donde las claves son cadenas y los valores pueden ser cualquier tipo compatible con JSON.
Summary class with a fromJson factory constructor instead of just using the raw Map from jsonDecode?Dart requiere que todos los datos JSON se conviertan a clases antes de usarse.
No exactamente.
Dart no requiere esto. Puedes usar mapas directos directamente en todo tu código.
Seguridad de tipos, autocompletado en el IDE y código más claro que documenta la estructura de datos esperada.
¡Correcto!
Una clase te proporciona comprobación de tipos en tiempo de compilación, autocompletado para propiedades y código autodocumentado.
summary.titlees más claro quemap['title'].jsonDecodeno puede parsear objetos JSON anidados sin una clase.No exactamente.
jsonDecodemaneja bien los objetos anidados, que se convierten en mapas anidados. Las clases sirven para un propósito diferente al análisis (parsing).Los mapas directos (raw maps) son más lentos de acceder que las propiedades de una clase.
No exactamente.
El rendimiento no es la razón principal. El acceso a mapas es bastante rápido en Dart. Piensa en la experiencia del desarrollador en su lugar.
Siguiente lección
#En la siguiente lección, aprenderás a
probar tu código Dart usando la librería package:test.
Escribirás pruebas para asegurarte de que tu
lógica de deserialización JSON esté funcionando correctamente.
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 22-01-2026. Ver fuente oreportar un problema.