Como decodificar JSON em Swift
Matheus dos Reis de Jesus
Posted on July 13, 2023
Contexto
Para quem está iniciando, talvez esteja se perguntando: porque preciso saber decodificar um conteúdo em JSON?
O formato JSON é amplamente utilizando em diversas linguagens para armazenar e transferir informações de maneira estruturada. Abaixo, alguns exemplos de cenários comuns:
- Arquivo JSON que armazena de configurações
- Consumir uma RESTFUL API que responda no formato JSON.
- String contendo informações no formato JSON.
Neste artigos iremos ver como ler e decodificar o formato JSON usando a linguagem Swift.
Sumário
Leitura do conteúdo JSON
O primeiro passo para ler um JSON em Swift é converter o seu conteúdo no formato Data
, um tipo da linguagem Swift, que será usado para decodificar a informação em um tipo que iremos definir mais à frente. Abaixo, temos os exemplos de conversão para cada cenário:
String
Abaixo, temos um exemplo de uma string contendo uma lista de posts no formato JSON:
let jsonContent = """
[
{
"id":1,
"title":"Como se tornar um programador",
"content":"Para se tornar um programador, é necessário estudar linguagens de programação e desenvolver habilidades de resolução de problemas.",
"created_at":"2023-04-18T14:00:00Z"
},
{
"id":2,
"title":"Os benefícios da meditação",
"content":"A meditação pode ajudar a reduzir o estresse, melhorar a qualidade do sono e aumentar a sensação de bem-estar.",
"created_at":"2023-04-18T14:00:00Z"
},
{
"id":3,
"title":"Receita de bolo de chocolate",
"content":"Para fazer um delicioso bolo de chocolate, você vai precisar de farinha de trigo, açúcar, ovos, óleo, cacau em pó e fermento em pó.",
"created_at":"2023-04-18T14:00:00Z"
}
]
"""
Dessa forma, usando as 3 aspas("""
), podemos declarar uma string com múltiplas linhas. Agora, podemos fazer a conversão da nossa string para o formato Data
:
// Usamos o .utf8 para converter a string
// para um padrão que permita acentuação
let data = Data(jsonContent.utf8)
Arquivo
Supondo que tenhamos um arquivo .json
que contenha uma lista de artigos:
[
{
"id":1,
"title":"Como se tornar um programador",
"content":"Para se tornar um programador, é necessário estudar linguagens de programação e desenvolver habilidades de resolução de problemas.",
"created_at":"2023-04-18T14:00:00Z"
},
{
"id":2,
"title":"Os benefícios da meditação",
"content":"A meditação pode ajudar a reduzir o estresse, melhorar a qualidade do sono e aumentar a sensação de bem-estar.",
"created_at":"2023-04-18T14:00:00Z"
},
{
"id":3,
"title":"Receita de bolo de chocolate",
"content":"Para fazer um delicioso bolo de chocolate, você vai precisar de farinha de trigo, açúcar, ovos, óleo, cacau em pó e fermento em pó.",
"created_at":"2023-04-18T14:00:00Z"
}
]
Considerando que o nome do nosso arquivo é artigos.json
, ele pode ser lido da seguinte forma:
// Caminho para um arquivo
let filePath = Bundle.main.path(forResource: "artigos", ofType: "json")
// Transforma o conteúdo do arquivo em Data
let data = try? Data(contentsOf: filePath)
Usamos o try?
antes do inicializador do Data porque a conversão do nosso arquivo para Data
pode falhar e causar uma exceção. Para não termos que lidar com exceções, usamos o try?
, que irá fazer com que o Data(contentsOf:)
retorne nil
caso um erro ocorra.
Requisição em API
Para fazer uma requisição em uma API, usaremos o método mais tradicional, URLSession.shared.dataTask(for:)
. Considerando uma URL fictícia que poderia nos fornecer a lista de artigos que desejamos obter, temos o seguinte código:
URLSession.shared.dataTask(with: url) { (data, response, error) in
// Verificamos se um objeto data recebido não é nulo
guard let data else { return }
// A partir daqui, executamos o passo de decodificação
// ...
}.resume()
Criação do tipo em Swift
Precisamos definir a estrutura dos objetos contida no nosso JSON, para qual os dados serão decodificados. Para isso, vamos criar um struct
que conforme com o protocolo Decodable
. Esse protocolo está disponível no framework Foundation
e é usado para definição de objetos que sejam decodificáveis. A seguir, temos a declaração do nosso tipo Post
:
struct Post: Decodable {
let id: Int
let title: String
let content: String
let createdAt: String
/*
* Definição dos atributos que possuem
* uma chave num formato diferente no JSON
* ex.: Nomes em snake_case
*/
enum CodingKeys: String, CodingKey {
case id, title, content
case createdAt = "created_at"
}
}
Cada atributo do objeto contido no nosso JSON é definido como uma propriedade do nosso struct
. Através do enum
CodingKeys
podemos definir uma associação entre chaves a serem "renomeadas" do JSON para atributos do nosso objeto. Acima, por exemplo, convertemos o created_at
(em snake-case) para createdAt
(em camel-case). Esse mesmo comportamento pode ser obtido atribuindo à propriedade keyDecodingStrategy
do JSONDecoder
o valor .convertFromSnakeCase
, que será visto no próximo tópico. O uso dessa propriedade elimina a necessidade de definirmos as associações para cada propriedade que esteja no formato snake-case.
Com nosso struct definido, poderemos fazer a decodificações de outras estruturas para ele, como um JSON, que é o nosso objetivo.
Decodificação
Agora que já temos um objeto Data
e um tipo definido podemos usá-los para decodificar nosso conteúdo JSON. Para isso, o framework Foundation
fornece uma classe JSONDecoder
criada exatamente com esse objetivo. Abaixo, temos um exemplo do processo de decodificação:
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let artigos = try? decoder.decode([Post].self, from: data)
print(artigos)
O método decode
da classe JSONDecoder
recebe dois parâmetros. O primeiro é o tipo do objeto a ser decodificado e o segundo é o objeto Data
que contém os dados obtidos anteriormente.
No exemplo deste artigo, o tipo a ser decodificado é uma lista do tipo Post
. O self
é usado para obter o tipo esperado, que é [Post]
(um array de Post
).
Vale ressaltar que o Data
esperado não pode ser nulo, então certifique-se de que seu objeto data
não é nil
antes de passá-lo para o decode
.
Conclusão
Conhecer essas 3 formas básicas de decodificar um JSON em Swift já te dá uma base suficiente para aplicar o conceito em diversos contextos. Abaixo, a documentação de alguns dos recursos utilizados nesse artigo:
Gostou deste artigo? Compartilhe e me siga para mais conteúdos como esse!
Capa por Ferenc Almasi na Unsplash
Posted on July 13, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.