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
shards
para 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.yml
só 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! Ocontent
no 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! 💎 🖤
Top 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!!!