Trabajo con JSON en Swift: análisis y serialización en la práctica
JSON (JavaScript Object Notation) es un formato ligero de intercambio de datos que se ha convertido en el estándar de facto para la comunicación entre cliente y servidor en el desarrollo móvil y web. En el ecosistema de Apple (iOS, macOS, watchOS, tvOS), el trabajo con JSON se realiza a través de potentes mecanismos integrados. En este artículo, analizaremos en detalle cómo analizar y serializar JSON en Swift con ejemplos reales, utilizando tanto el protocolo moderno Codable como el clásico JSONSerialization.
El artículo está dirigido a desarrolladores que ya conocen los fundamentos de Swift y desean trabajar con confianza con solicitudes de red y almacenamiento local de datos en formato JSON.
1. Fundamentos de JSON y su lugar en las aplicaciones Swift
JSON es un formato de texto basado en dos estructuras: objetos (conjuntos de pares clave-valor) y arreglos (listas ordenadas). En Swift, estas estructuras corresponden a Dictionary y Array. Los tipos de datos en JSON son limitados: cadenas, números, valores booleanos, null, objetos y arreglos.
Un escenario típico de uso de JSON en una aplicación iOS/macOS es el siguiente:
- Obtener una cadena JSON del servidor (a través de URLSession).
- Analizar el JSON en modelos de Swift (por ejemplo, estructuras o clases).
- Procesar los datos y mostrarlos en la interfaz.
- Serializar (transformación inversa) los modelos a JSON para enviarlos al servidor.
Apple proporciona dos enfoques principales para trabajar con JSON: JSONSerialization (de bajo nivel, pero flexible) y Codable (de alto nivel, con seguridad de tipos, recomendado desde Swift 4+).
2. Análisis de JSON con Codable (método recomendado)
El protocolo Codable combina Encodable (para serialización) y Decodable (para análisis). Es la forma más simple y segura de trabajar con JSON en Swift.
Ejemplo 1: Análisis de un objeto JSON simple
Supongamos que el servidor devuelve el siguiente JSON:
{ "userId": 1, "id": 1, "title": "Ejemplo de tarea", "completed": false}Creemos una estructura de modelo que cumpla con Codable:
struct TodoItem: Codable { let userId: Int let id: Int let title: String let completed: Bool}Ahora realicemos el análisis de la cadena JSON:
let jsonString = """{ "userId": 1, "id": 1, "title": "Ejemplo de tarea", "completed": false}"""
if let jsonData = jsonString.data(using: .utf8) { let decoder = JSONDecoder() do { let todo = try decoder.decode(TodoItem.self, from: jsonData) print("Tarea: \\(todo.title), completada: \\(todo.completed)") } catch { print("Error de análisis: \\(error.localizedDescription)") }}Ejemplo 2: Análisis de un arreglo de objetos
Si el servidor devuelve un arreglo de tareas:
[ {"userId": 1, "id": 1, "title": "Tarea 1", "completed": false}, {"userId": 1, "id": 2, "title": "Tarea 2", "completed": true}]El análisis se realiza igual de simple: solo hay que especificar el tipo de arreglo:
let todoArray = try decoder.decode([TodoItem].self, from: jsonData)2.1. Claves personalizadas y snake_case
A menudo, JSON usa el formato snake_case (por ejemplo, user_id), mientras que en Swift se usa camelCase (userId). JSONDecoder puede transformar las claves automáticamente:
decoder.keyDecodingStrategy = .convertFromSnakeCaseSi es necesario establecer una correspondencia no estándar, use la enumeración CodingKeys:
struct User: Codable { let fullName: String let emailAddress: String
enum CodingKeys: