29. Creación de Json (Simulando Api)
MusicApp
Introducción
¡Hola de nuevo! En este vídeo vamos a crear la estructura de datos para nuestra aplicación de música. Vamos a simular una API local usando un archivo JSON que contenga toda la información que necesitaremos: imágenes, títulos, y configuraciones para cada sección de nuestra app.
Paso 1: Estructura del Proyecto
Primero, vamos a organizar nuestro proyecto. Necesitamos crear una carpeta src y dentro de ella organizar nuestras imágenes y datos:
text
MusicApp/
├── src/
│ ├── images/
│ │ ├── banner.png
│ │ ├── right-arrow.png
│ │ ├── moodweekend/
│ │ │ ├── 1.png
│ │ │ ├── 2.png
│ │ │ ├── 3.png
│ │ │ ├── 4.png
│ │ │ └── 5.png
│ │ ├── topalbums/
│ │ │ ├── 1.png
│ │ │ ├── 2.png
│ │ │ ├── 3.png
│ │ │ └── 4.png
│ │ └── browseall/
│ │ ├── 1.png
│ │ ├── 2.png
│ │ ├── 3.png
│ │ ├── 4.png
│ │ ├── 5.png
│ │ ├── 6.png
│ │ ├── 7.png
│ │ ├── 8.png
│ │ ├── 9.png
│ │ └── 10.png
│ └── data.js
├── App.js
└── ...
Paso 2: Crear el Archivo data.js
Dentro de la carpeta src, creamos un nuevo archivo llamado data.js:
src/data.js
javascript
// Archivo de datos que simula una API
// Contiene toda la información estática de la aplicación
const data = {
// Sección Banner
banner: {
img: require('./images/banner.png'),
title: "Descubre nueva música",
subtitle: "Explora miles de canciones y álbumes"
},
// Sección Mood Weekend
moodWeekend: {
title: "Mood Weekend",
rightIcon: require('./images/right-arrow.png'),
images: [
{
id: 1,
img: require('./images/moodweekend/1.png'),
title: "Relax",
color: "#667eea"
},
{
id: 2,
img: require('./images/moodweekend/2.png'),
title: "Energía",
color: "#f093fb"
},
{
id: 3,
img: require('./images/moodweekend/3.png'),
title: "Nostalgia",
color: "#f5576c"
},
{
id: 4,
img: require('./images/moodweekend/4.png'),
title: "Felicidad",
color: "#4facfe"
},
{
id: 5,
img: require('./images/moodweekend/5.png'),
title: "Concentración",
color: "#43e97b"
}
]
},
// Sección Top Albums
topAlbums: {
title: "Top Albums",
rightIcon: require('./images/right-arrow.png'),
images: [
{
id: 1,
img: require('./images/topalbums/1.png'),
title: "Midnight Dreams",
artist: "The Dreamers",
plays: "2.5M"
},
{
id: 2,
img: require('./images/topalbums/2.png'),
title: "Summer Vibes",
artist: "Ocean View",
plays: "1.8M"
},
{
id: 3,
img: require('./images/topalbums/3.png'),
title: "Urban Legends",
artist: "City Lights",
plays: "3.2M"
},
{
id: 4,
img: require('./images/topalbums/4.png'),
title: "Echoes of Time",
artist: "Nova Sequence",
plays: "1.2M"
}
]
},
// Sección Browse All
browseAll: {
title: "Browse All",
images: [
{
id: 1,
img: require('./images/browseall/1.png'),
title: "Pop",
color: "#8A2387"
},
{
id: 2,
img: require('./images/browseall/2.png'),
title: "Rock",
color: "#F27121"
},
{
id: 3,
img: require('./images/browseall/3.png'),
title: "Hip Hop",
color: "#E94057"
},
{
id: 4,
img: require('./images/browseall/4.png'),
title: "Jazz",
color: "#4A00E0"
},
{
id: 5,
img: require('./images/browseall/5.png'),
title: "Electrónica",
color: "#24C6DC"
},
{
id: 6,
img: require('./images/browseall/6.png'),
title: "Indie",
color: "#514A9D"
},
{
id: 7,
img: require('./images/browseall/7.png'),
title: "Reggaetón",
color: "#FF8008"
},
{
id: 8,
img: require('./images/browseall/8.png'),
title: "Clásica",
color: "#1D976C"
},
{
id: 9,
img: require('./images/browseall/9.png'),
title: "R&B",
color: "#DA4453"
},
{
id: 10,
img: require('./images/browseall/10.png'),
title: "Country",
color: "#D66D75"
}
]
}
};
export default data;
Paso 3: Explicación del Código
1. Estructura del objeto data:
javascript
const data = {
// Propiedades principales
};
Creamos un objeto constante que contendrá todos nuestros datos estructurados.
2. Sección Banner:
javascript
banner: {
img: require('./images/banner.png'),
title: "Descubre nueva música",
subtitle: "Explora miles de canciones y álbumes"
}
require(): Método de React Native para cargar imágenes locales
Contiene la imagen, título y subtítulo del banner principal
3. Sección Mood Weekend:
javascript
moodWeekend: {
title: "Mood Weekend",
rightIcon: require('./images/right-arrow.png'),
images: [...]
}
rightIcon: Icono de flecha derecha para navegación
images: Array de objetos, cada uno con:
id: Identificador único
img: Imagen del mood
title: Nombre del mood
color: Color de fondo
4. Sección Top Albums:
Similar a Mood Weekend pero con información específica de álbumes:
javascript
{
id: 1,
img: require('./images/topalbums/1.png'),
title: "Midnight Dreams",
artist: "The Dreamers",
plays: "2.5M"
}
5. Sección Browse All:
Contiene 10 categorías musicales, cada una con imagen, título y color.
Paso 4: Crear Versión Alternativa con Más Detalles
src/data-enhanced.js (opcional)
javascript
// Versión mejorada con más datos y categorías
const musicData = {
appInfo: {
name: "MusicApp",
version: "1.0.0",
developer: "Tu Nombre"
},
banner: {
id: "banner_001",
type: "promotional",
img: require('./images/banner.png'),
title: "🎵 Descubre Nueva Música",
subtitle: "Explora miles de canciones y álbumes",
ctaText: "Comenzar Ahora",
backgroundColor: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
textColor: "#FFFFFF"
},
moodWeekend: {
id: "section_mood",
type: "horizontal_scroll",
title: "Mood Weekend",
description: "Playlists para cada estado de ánimo",
rightIcon: {
img: require('./images/right-arrow.png'),
action: "view_all_moods"
},
items: [
{
id: "mood_001",
type: "mood",
img: require('./images/moodweekend/1.png'),
title: "Relax",
description: "Música para relajarte",
color: "#667eea",
songCount: 125,
duration: "8h 45m"
},
// ... más moods
]
},
topAlbums: {
id: "section_top_albums",
type: "horizontal_scroll",
title: "🔥 Top Albums",
description: "Los álbumes más escuchados esta semana",
filters: ["Hoy", "Esta semana", "Este mes"],
rightIcon: {
img: require('./images/right-arrow.png'),
action: "view_all_albums"
},
items: [
{
id: "album_001",
type: "album",
rank: 1,
img: require('./images/topalbums/1.png'),
title: "Midnight Dreams",
artist: {
name: "The Dreamers",
id: "artist_001"
},
year: 2023,
genre: ["Indie", "Alternative"],
plays: "2.5M",
duration: "45:20",
songs: 12,
isExplicit: false
},
// ... más álbumes
]
},
browseAll: {
id: "section_browse",
type: "grid",
title: "🌍 Browse All",
description: "Explora todas las categorías musicales",
layout: "2_columns", // o "3_columns" en tablets
items: [
{
id: "category_001",
type: "category",
img: require('./images/browseall/1.png'),
title: "Pop",
description: "Música popular contemporánea",
color: "#8A2387",
gradient: ["#8A2387", "#F27121"],
songCount: "50K+",
featuredArtists: ["Taylor Swift", "Dua Lipa", "The Weeknd"]
},
// ... más categorías
]
},
recentlyPlayed: {
id: "section_recent",
type: "horizontal_scroll",
title: "▶️ Recently Played",
items: [
// Datos de reproducción reciente
]
},
userProfile: {
username: "Usuario",
favoriteGenres: ["Pop", "Rock", "Hip Hop"],
playlists: 15,
followers: 245,
following: 189
}
};
// Función para obtener datos específicos
export const getSectionData = (sectionId) => {
switch(sectionId) {
case 'banner':
return musicData.banner;
case 'moodWeekend':
return musicData.moodWeekend;
case 'topAlbums':
return musicData.topAlbums;
case 'browseAll':
return musicData.browseAll;
default:
return null;
}
};
// Función para buscar items
export const searchItems = (query) => {
const allItems = [
...musicData.moodWeekend.items,
...musicData.topAlbums.items,
...musicData.browseAll.items
];
return allItems.filter(item =>
item.title.toLowerCase().includes(query.toLowerCase()) ||
(item.artist && item.artist.name.toLowerCase().includes(query.toLowerCase()))
);
};
export default musicData;
Paso 5: Actualizar App.js para Usar los Datos
App.js actualizado:
javascript
import React from 'react';
import {
View,
Text,
StyleSheet,
SafeAreaView,
ScrollView,
Image,
TouchableOpacity
} from 'react-native';
// Importamos nuestros datos
import data from './src/data';
const App = () => {
return (
<SafeAreaView style={styles.container}>
<ScrollView style={styles.scrollView}>
{/* Banner */}
<View style={styles.banner}>
<Image
source={data.banner.img}
style={styles.bannerImage}
resizeMode="cover"
/>
<View style={styles.bannerOverlay}>
<Text style={styles.bannerTitle}>{data.banner.title}</Text>
<Text style={styles.bannerSubtitle}>{data.banner.subtitle}</Text>
</View>
</View>
{/* Mood Weekend Section */}
<View style={styles.section}>
<View style={styles.sectionHeader}>
<Text style={styles.sectionTitle}>{data.moodWeekend.title}</Text>
<TouchableOpacity>
<Image
source={data.moodWeekend.rightIcon}
style={styles.rightIcon}
/>
</TouchableOpacity>
</View>
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
style={styles.horizontalScroll}
>
{data.moodWeekend.images.map((item) => (
<TouchableOpacity key={item.id} style={styles.moodCard}>
<Image
source={item.img}
style={styles.moodImage}
resizeMode="cover"
/>
<Text style={styles.moodTitle}>{item.title}</Text>
</TouchableOpacity>
))}
</ScrollView>
</View>
{/* Top Albums Section */}
<View style={styles.section}>
<View style={styles.sectionHeader}>
<Text style={styles.sectionTitle}>{data.topAlbums.title}</Text>
<TouchableOpacity>
<Image
source={data.topAlbums.rightIcon}
style={styles.rightIcon}
/>
</TouchableOpacity>
</View>
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
style={styles.horizontalScroll}
>
{data.topAlbums.images.map((album) => (
<TouchableOpacity key={album.id} style={styles.albumCard}>
<Image
source={album.img}
style={styles.albumImage}
resizeMode="cover"
/>
<View style={styles.albumInfo}>
<Text style={styles.albumTitle}>{album.title}</Text>
<Text style={styles.albumArtist}>{album.artist}</Text>
<Text style={styles.albumPlays}>{album.plays} plays</Text>
</View>
</TouchableOpacity>
))}
</ScrollView>
</View>
{/* Browse All Section */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>{data.browseAll.title}</Text>
<View style={styles.browseGrid}>
{data.browseAll.images.map((category) => (
<TouchableOpacity
key={category.id}
style={[styles.categoryCard, { backgroundColor: category.color }]}
>
<Image
source={category.img}
style={styles.categoryImage}
resizeMode="cover"
/>
<Text style={styles.categoryTitle}>{category.title}</Text>
</TouchableOpacity>
))}
</View>
</View>
</ScrollView>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#121212',
},
scrollView: {
flex: 1,
},
banner: {
height: 200,
borderRadius: 15,
margin: 15,
overflow: 'hidden',
position: 'relative',
},
bannerImage: {
width: '100%',
height: '100%',
},
bannerOverlay: {
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'rgba(0,0,0,0.5)',
padding: 20,
},
bannerTitle: {
fontSize: 24,
fontWeight: 'bold',
color: '#FFFFFF',
},
bannerSubtitle: {
fontSize: 16,
color: '#CCCCCC',
marginTop: 5,
},
section: {
paddingHorizontal: 15,
marginBottom: 30,
},
sectionHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 15,
},
sectionTitle: {
fontSize: 22,
fontWeight: 'bold',
color: '#FFFFFF',
},
rightIcon: {
width: 24,
height: 24,
tintColor: '#1DB954',
},
horizontalScroll: {
marginHorizontal: -15,
},
moodCard: {
width: 150,
marginRight: 15,
},
moodImage: {
width: 150,
height: 150,
borderRadius: 10,
marginBottom: 10,
},
moodTitle: {
fontSize: 16,
fontWeight: '600',
color: '#FFFFFF',
textAlign: 'center',
},
albumCard: {
width: 180,
marginRight: 15,
backgroundColor: '#1E1E1E',
borderRadius: 10,
overflow: 'hidden',
},
albumImage: {
width: '100%',
height: 180,
},
albumInfo: {
padding: 10,
},
albumTitle: {
fontSize: 16,
fontWeight: 'bold',
color: '#FFFFFF',
marginBottom: 5,
},
albumArtist: {
fontSize: 14,
color: '#B3B3B3',
marginBottom: 5,
},
albumPlays: {
fontSize: 12,
color: '#1DB954',
},
browseGrid: {
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-between',
marginHorizontal: -5,
},
categoryCard: {
width: '48%',
height: 100,
borderRadius: 10,
marginBottom: 10,
overflow: 'hidden',
position: 'relative',
},
categoryImage: {
width: '100%',
height: '100%',
opacity: 0.7,
},
categoryTitle: {
position: 'absolute',
bottom: 10,
left: 10,
fontSize: 18,
fontWeight: 'bold',
color: '#FFFFFF',
},
});
export default App;
Paso 6: Ventajas de Esta Estructura
✅ Ventajas de usar data.js como API simulada:
Organización centralizada: Todos los datos en un solo lugar
Fácil mantenimiento: Cambios en un solo archivo
Simulación realista: Estructura similar a una API real
Rápido desarrollo: Sin dependencia de servidores externos
Fácil migración: Cambiar a API real será sencillo
🔄 Cómo migrar a API real en el futuro:
javascript
// Futura implementación con API real
const fetchData = async () => {
try {
const response = await fetch('https://api.musicapp.com/data');
const realData = await response.json();
return realData;
} catch (error) {
// Fallback a datos locales
return data;
}
};
Paso 7: Consejos Adicionales
1. Tipos de datos para imágenes:
PNG: Para logos y gráficos con transparencia
JPG: Para fotografías y fondos
SVG: Para iconos escalables (necesita librería adicional)
2. Optimización de imágenes:
Reducir tamaño de imágenes antes de incluirlas
Usar dimensiones apropiadas para móviles
Considerar usar CDN para producción
3. Estructura escalable:
javascript
// Para proyectos grandes
src/
├── data/
│ ├── index.js
│ ├── banners.js
│ ├── moods.js
│ ├── albums.js
│ └── categories.js
├── images/
└── ...
Resumen
Hemos creado un archivo data.js que actúa como una API simulada para nuestra aplicación. Este archivo:
Contiene todas las imágenes organizadas por secciones
Define la estructura de datos para cada componente
Permite fácil mantenimiento y actualización
Prepara el proyecto para futura integración con API real
En el próximo video, crearemos los componentes que consumirán estos datos y darán vida a nuestra interfaz de usuario.
¡Guardamos los cambios y nos vemos en el próximo tutorial
Comentarios
Publicar un comentario