Trabalho com JSON em Swift: parsing e serialização na prática
JSON (JavaScript Object Notation) é um formato leve de troca de dados que se tornou o padrão de facto para comunicação entre cliente e servidor no desenvolvimento móvel e web. No ecossistema Apple (iOS, macOS, watchOS, tvOS), o trabalho com JSON é feito através de mecanismos internos poderosos. Neste artigo, vamos detalhar como fazer parsing e serializar JSON em Swift com exemplos reais, usando tanto o protocolo moderno Codable quanto o clássico JSONSerialization.
O artigo é destinado a desenvolvedores que já conhecem os fundamentos do Swift e desejam trabalhar com confiança em requisições de rede e armazenamento local de dados no formato JSON.
1. Fundamentos do JSON e seu lugar em aplicativos Swift
JSON é um formato textual baseado em duas estruturas: objetos (conjuntos de pares chave-valor) e arrays (listas ordenadas). Em Swift, essas estruturas correspondem a Dictionary e Array. Os tipos de dados em JSON são limitados: strings, números, valores booleanos, null, objetos e arrays.
Um cenário típico de uso de JSON em um aplicativo iOS/macOS é assim:
- Obter uma string JSON do servidor (via URLSession).
- Fazer parsing do JSON para modelos Swift (por exemplo, structs ou classes).
- Processar os dados e exibi-los na interface.
- Serializar (conversão reversa) os modelos para JSON para enviar ao servidor.
A Apple fornece duas abordagens principais para trabalhar com JSON: JSONSerialization (de baixo nível, mas flexível) e Codable (de alto nível, type-safe, recomendado a partir do Swift 4+).
2. Parsing de JSON com Codable (método recomendado)
O protocolo Codable combina Encodable (para serialização) e Decodable (para parsing). Esta é a maneira mais simples e segura de trabalhar com JSON em Swift.
Exemplo 1: Parsing de um objeto JSON simples
Suponha que o servidor retorne o seguinte JSON:
{ "userId": 1, "id": 1, "title": "Exemplo de tarefa", "completed": false}Criaremos uma estrutura de modelo que esteja em conformidade com Codable:
struct TodoItem: Codable { let userId: Int let id: Int let title: String let completed: Bool}Agora, faremos o parsing da string JSON:
let jsonString = """{ "userId": 1, "id": 1, "title": "Exemplo de tarefa", "completed": false}"""
if let jsonData = jsonString.data(using: .utf8) { let decoder = JSONDecoder() do { let todo = try decoder.decode(TodoItem.self, from: jsonData) print("Tarefa: \\(todo.title), concluída: \\(todo.completed)") } catch { print("Erro de parsing: \\(error.localizedDescription)") }}Exemplo 2: Parsing de um array de objetos
Se o servidor retornar um array de tarefas:
[ {"userId": 1, "id": 1, "title": "Tarefa 1", "completed": false}, {"userId": 1, "id": 2, "title": "Tarefa 2", "completed": true}]O parsing é feito de forma igualmente simples — basta especificar o tipo do array:
let todoArray = try decoder.decode([TodoItem].self, from: jsonData)2.1. Chaves personalizadas e snake_case
Frequentemente, o JSON usa o formato snake_case (por exemplo, user_id), enquanto em Swift é adotado o camelCase (userId). O JSONDecoder consegue converter as chaves automaticamente:
decoder.keyDecodingStrategy = .convertFromSnakeCaseSe for necessário definir um mapeamento não padrão, use a enumeração CodingKeys:
struct User: Codable { let fullName: String let emailAddress: String
enum CodingKeys: