Se você alguma vez já pensou em como seria trabalhar com a leitura de arquivos JSON utilizando Crystal, saiba que este é o lugar certo! Aqui veremos como podemos realizar manipulações simples de valores em JSON, trabalhando com variáveis, arrays, hashs, entre outras maneiras, manipulando nossas chaves com variáveis!
O que é JSON
O nome JSON vem de "JavaScript Object Notation", sendo um formato compacto de padrão aberto para troca e manipulação de dados simples, criado ainda nos anos 2000 (mais especificamente em 2002) utilizando um formato de chave-valor (atributo-valor).
Ok, mas, como seria o formato de um arquivo JSON?
[
{
"mensagem": "fala tropa"
},
{
"resposta": "eai"
}
]
As chaves/atributos seriam os campos
"mensagem"e"resposta", na qual seu valor está atribuído logo após dos dois pontos (":"), sendo separadas por chaves ("{ }") e vírgula indicando o próximo atributo completo.
Trabalhando com Crystal
Abrindo seu diretório de trabalho, crie um novo diretório para trabalharmos com este projeto, na qual vamos precisar de algumas "dependências" antes de iniciarmos:
- Tenha certeza de ter o Crystal instalado corretamente na sua máquina
- Prepare o editor de código favorito no diretório que foi criado
- Caso não tenha instalado o Crystal ainda clique aqui para saber mais!
Após abrir seu diretório de trabalho, caso queira iniciar o
shardspara criação de um arquivo para controle de projeto, execute em seu terminal:
$ shards init
Seu arquivo shard.yml deverá seguir o seguinte formato:
name: json-reader
version: 0.1.0
authors:
- João Lanjoni <guto@lanjoni.dev>
description: |
JSON reader
targets:
teste:
main: src/main.cr
license: MIT
Agora crie um diretório chamado src, nele vamos colocar todo o nosso código trabalhado utilizando Crystal! Crie também um diretório chamado content na raiz do projeto para conter todos os nossos arquivos em formato JSON!
Sendo assim, basta adicionar um arquivo no formato JSON com o nome que desejar no diretório content e adicionar um arquivo main.cr no diretório src, assim, ficaremos com nossa árvore:
json-reader/
├── content/
│ └── index.json
├── src/
│ └── main.cr
└── shard.yml
Lembrando que o
shard.ymlsó existe se você iniciou o shards dentro de seu projeto!
Mãos na massa (no teclado)
Primeiramente vamos criar nosso arquivo JSON, por isso, seguindo o template passado acima crie um arquivo .json dentro do diretório content! Com ele vamos manipular os valores lá existentes!
Agora abra seu arquivo src/main.cr no seu editor de código favorito para podermos manipular melhor nosso projeto!
Abrindo seu arquivo primeiramente vamos importar a biblioteca json para trabalharmos com arquivos neste formato, assim, adicione em seu código:
require "json"
Toda biblioteca pode ser adicionada com o comando
require!
Para informarmos qual será o arquivo a ser lido, vamos realizar uma simples passagem por argumento/opção ao executar nosso projeto! Assim, caso queira se aprofundar um pouco mais sobre a passagem de argumentos na linha de comando com Crystal clique aqui. Dessa forma, vamos salvar o conteúdo do arquivo JSON em uma variável:
content = File.read("content/#{ARGV[0]}")
Para recebermos o primeiro argumento/opção utilizaremos o
ARGV[0], afinal, a posição 0 é a primeira no array de valores passados como opções! Ocontentno começo significa que precisamos passar apenas o nome do arquivo, afinal, já será buscado um arquivo de mesmo nome no diretório especificado!
Certo, mas, existe ainda o caso do usuário não adicionar nenhuma opção, certo? Neste caso o código nem deve continuar, afinal, se um arquivo JSON não for especificado, logo, não podemos realizar a manipulação! Assim, antes, adicionamos uma simples verificação:
if ARGV.size != 1
puts "É necessário passar o nome do arquivo como parâmetro!"
exit 1
end
O tamanho sendo diferente de 1 demonstra que foram passados ou mais de um argumento ou nenhum, por isso, em ambos os casos, devemos rejeitar a execução!
Para realizar o parse de nosso JSON existem algumas formas, vamos começar com a mais simples: JSON de chaves únicas! Veja o JSON de exemplo abaixo:
{
"teste": "oi",
"teste2": "tchau"
}
Perceba que este formato não possui colchetes em seu início, indicando não ser um array!
Para realizar o parse vamos utilizar uma função nativa do Crystal para realizar a leitura de um JSON e depois convertê-lo em um Hash de Strings!
hash_content = Hash(String, String).from_json(content)
puts hash_content # {"teste" => "oi", "teste2" => "tchau"}
Desta forma vamos montar uma variável com nome
hash_content, tendo em seu conteúdo um hash com chave valor de String para String, trazendo estes dados de um JSON
Logo, nosso código final será algo como:
require "json"
# Verificação de argumentos sendo igual a 1
if ARGV.size != 1
puts "É necessário passar o nome do arquivo como parâmetro!"
exit 1
end
# Carregando o conteúdo do arquivo JSON
content = File.read("content/#{ARGV[0]}")
# Transformando os dados do arquivo JSON em um Hash de String => String
hash_content = Hash(String, String).from_json(content)
# Imprimindo o conteúdo da variável
puts hash_content # {"teste" => "oi", "teste2" => "tchau"}
Podemos executar de duas formas:
-
Utilizando
shards:
$ shards run -- content.json
-
Utilizando o próprio
crystal:
$ crystal run src/main.cr content.json
Certo, mas, e se quiséssemos apenas o retorno da chave teste?
puts hash_content["teste"] # oi
Assim, conseguimos manipular nossos dados no arquivo JSON, podendo trazer as chaves específicas para cada item!
Arrays de JSONs
Certo, mas, a maioria dos JSONs que vamos encontrar precisam ser "parseados" utilizando formatos de Array... Como podemos fazer isso? Bom, existem duas formas específicas para realizarmos essa tarefa, bora lá?
Primeira forma: Array de Hash
Basicamente vamos montar um array com seu tipo interno sendo hash! Mas, como isso ficaria na prática? Bom, primeiro vou repassar agora o arquivo JSON que estaremos trabalhando:
[
{
"teste": "fala tropa"
},
{
"teste2": "eai"
}
]
Vamos primeiramente definir que estamos trabalhando com um array, mas, no momento de definir o tipo do array vamos trocar para Hash(String, String), veja:
json = Array(Hash(String, String)).from_json(content)
puts json # [{"teste" => "fala tropa"}, {"teste2" => "eai"}]
Perceba que basicamente envolvemos o formato de hash anterior no array, correto? Assim podemos trabalhar com nossos arrays de JSONs da forma que preferirmos! Mas, como eu poderia trazer apenas o conteúdo da chave "teste"? Simples, veja dois exemplos abaixo:
puts json[0] # {"teste" => "fala tropa"}
puts json[0]["teste"] # fala tropa
Assim, conseguimos manipular nosso JSON!
Caso o formato de chave não seja sempre String, podemos ainda criar um alias para manipular os tipos passados por Hash ou então apenas adicionarmos um operador pipe ("|") demonstrando que o tipo pode variar, sendo assim seria algo como:
Hash(String | Float64, String | Int32)
Segunda forma: File.open
Podemos ainda utilizar o File.open para abrir um arquivo e trabalhar com seu conteúdo (na qual deixo os créditos para a cherry por ter passado na live e deixado esse detalhe importantíssimo), sem a necessidade da criação de uma variável para realizar esse trabalho (como estávamos fazendo com a variável content). Veja uma implementação abaixo:
json = File.open("content/#{ARGV[0]}") do |file|
JSON.parse(file)
end
puts json # [{"teste" => "fala tropa"}, {"teste2" => "eai"}]
puts json[0] # {"teste" => "fala tropa"}
puts json[0]["teste"] # fala tropa
Neste exemplo realizamos um simples "parse" de valores e atualizamos na variável de nome
json, podendo trabalhar com os valores no mesmo formato que anteriormente!
Assim, nosso projeto completo finaliza na segunda forma! Veja como ficou nosso código finalizado:
require "json"
if ARGV.size != 1
puts "É necessário passar o nome do arquivo como parâmetro!"
exit 1
end
json = File.open("content/#{ARGV[0]}") do |file|
JSON.parse(file)
end
puts json # [{"teste" => "fala tropa"}, {"teste2" => "eai"}]
Finalização
Com este guia e pequeno artigo você aprendeu a como manipular arquivos JSON e dados vindo de outros arquivos utilizando Crystal, baseando-se no modelo chave-valor que é oferecido, podendo criar comandos, leituras específicas, entre outros tipos de projetos! Para acessar o código desenvolvido neste artigo basta clicar aqui!
Nos vemos na próxima, até mais! Cristalize ainda mais o seu dia! 💎 🖤
Oldest comments (2)
Bom demais! Curti muito a capacidade de tipar pelo
from_json, fica super simples de garantir segurança com tiposConteúdo incrível! Espero ver mais dele por aqui!!!