Trabalho com JSON em Swift: parsing e serialização
JSON (JavaScript Object Notation) é um formato leve de troca de dados, amplamente utilizado em serviços web e aplicativos móveis. No ecossistema Apple (iOS, macOS, watchOS, tvOS), o trabalho com JSON é uma parte essencial do desenvolvimento: desde o carregamento de dados do servidor até a salvaguarda das configurações do aplicativo. Neste artigo, veremos detalhadamente como realizar parsing (decodificação) e serialização (codificação) de JSON em Swift, usando os protocolos integrados Codable, JSONDecoder e JSONEncoder.
1. Fundamentos do Codable: modelo de dados
A abordagem moderna para trabalhar com JSON em Swift é baseada no protocolo Codable, que combina dois protocolos: Encodable (para serialização) e Decodable (para parsing). Para que sua estrutura ou classe possa ser convertida para JSON e vice-versa, basta declará-la como Codable.
Vamos considerar um exemplo de modelo de usuário:
struct User: Codable { let id: Int let name: String let email: String let isActive: Bool}Se as chaves no JSON diferirem dos nomes das propriedades em Swift (por exemplo, usando snake_case em vez de camelCase), você pode usar a enumeração CodingKeys:
struct User: Codable { let id: Int let fullName: String let email: String let isActive: Bool
enum CodingKeys: String, CodingKey { case id case fullName = "full_name" case email case isActive = "is_active" }}2. Parsing de JSON com JSONDecoder
Para converter uma string JSON ou dados em objetos Swift, usa-se JSONDecoder. O método principal é decode(_:from:), que recebe o tipo de dados (que corresponde a Decodable) e um objeto Data.
Exemplo de parsing de uma string JSON obtida de uma API:
let jsonString = """{ "id": 1, "name": "Ivan Petrov", "email": "ivan@example.com", "is_active": true}"""
let jsonData = Data(jsonString.utf8)
do { let decoder = JSONDecoder() let user = try decoder.decode(User.self, from: jsonData) print("Usuário: \\(user.name), email: \\(user.email)")} catch { print("Erro de decodificação: \\(error.localizedDescription)")}Frequentemente, o JSON chega como um array de objetos. Nesse caso, basta especificar o tipo [User].self:
let jsonArrayString = """[ {"id": 1, "name": "Ivan", "email": "ivan@test.com", "is_active": true}, {"id": 2, "name": "Maria", "email": "maria@test.com", "is_active": false}]"""
let jsonArrayData = Data(jsonArrayString.utf8)
do { let users = try JSONDecoder().decode([User].self, from: jsonArrayData) users.forEach { print($0.name) }} catch { print("Erro: \\(error)")}3. Serialização de objetos em JSON com JSONEncoder
O processo inverso — converter um objeto Swift em JSON — é realizado com JSONEncoder. O método encode(_:) retorna um objeto Data, que pode então ser convertido em uma string ou enviado para o servidor.
let user = User(id: 3, fullName: "Alexei Smirnov", email: "alex@example.com", isActive: true)
do { let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted // para formatação legível let jsonData = try encoder.encode(user) if let jsonString = String(data: jsonData, encoding: .utf8) { print(jsonString) }} catch { print("Erro de codificação: \\(error)")}A saída será assim:
{ "id" : 3, "full_name" : "Alexei Smirnov", "email" : "alex@example.com", "is_active" : true}Observe que o JSO