# JQ - Instalação e Explicação

%[https://youtu.be/ItqL0iyJYd4] 

---

## Introdução

`JSON` é um formato de dados estruturado amplamente utilizado na maioria das APIs e serviços modernos para compartilhar dados. É particularmente popular em aplicativos da web devido à sua natureza leve e compatibilidade como seu próprio nome sugere, o `JavaScript`.

Infelizmente terminais de comando como o `bash` não podem interpretar e trabalhar com `json` diretamente. Isso significa que trabalhar com `json` por meio da linha de comando pode ser complicado, vejamos por exemplo uma chamada para a API do filme Star Wars:

```bash
curl https://swapi.dev/api/people
```

E obtemos uma resposta em `json` com informações sobre os personagens do filme:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663176625251/fPwGv_QFh.png align="center")

Bom, podemos ver que o `json` retornado não é muito amigável para nossa leitura, mas não se preocupe porque há uma forma simples e fácil de resolver isso, e o nome da solução se chama `jq` que acabará se tornando uma das suas ferramentas favoritas!

2- Veja como o mesmo `request` ficaria usando o `jq`:

```bash
curl https://swapi.dev/api/people | jq '.'
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663176694642/Fv6wrVjQP.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">☑</div>
<div data-node-type="callout-text"><strong>WOW!</strong> Visualmente falando, ficou muito melhor né? 🥳</div>
</div>

---

## Instalação

1- Abra seu terminal e digite o comando:

```bash
sudo apt install jq
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663176757643/S5UnnetG3.png align="center")

2- Verifique a instalação com o comando:

```bash
jq --version
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663176788925/QJBGJV-SX.png align="center")

---

## Como usar o JQ

`JQ` é mais do que apenas "embelezar" o json em seu bash, ele foi construído em torno do conceito de filtros, como veremos abaixo e existem muitos filtros que podemos usar e combinar sem esforços usando o caractere "`pipe`" `|` para manipular os dados do json.

Então vamos começar pelo filtro mais simples de todos, que também será o que você acabará usando com mais frequência:

```bash
curl https://swapi.dev/api/people | jq '.'
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663176875759/-qgc9wYGX.png align="center")

**Vamos entender o que aconteceu aqui:**

* Adicionamos ao final do nosso comando `| jq '.'`
    
* Esse `'.'` é um filtro que estamos dizendo ao jq `"hey, pegue todos os dados e imprima em um formato json visualmente mais bonito para mim"`.
    

---

**Avançando...**

Ok, já conseguimos ver o json melhor agora, mas imagino que você deve estar se perguntando nesse momento "Certo, é só isso? Mas como que eu pego apenas o nome de um personagem por exemplo?".

Se você se questionou sobre isso, estamos no caminho certo aqui. Vamos detalhar como podemos filtrar apenas o nome do personagem Star Wars no meio de toda essa informação:

1- Se olharmos bem, um json é constituído de `"chave":"valor"` ou no inglês `"key":"value"`:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663176973412/hhiiP7x-3.png align="center")

2- E a key `name` está dentro de um `array` (matriz) chamado `results`:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663177017134/OdFWXAULb.png align="center")

3- Então para filtrarmos, poderíamos começar com:

```bash
curl https://swapi.dev/api/people | jq '.results'
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663177053058/_YyUkyNBR.png align="center")

**Vamos entender o que aconteceu aqui:**

* Adicionamos ao final do nosso comando `| jq '.results'`
    
* Esse `'.results'` é um filtro que estamos dizendo ao jq `"hey, pegue todos os dados do array (matriz) chamado results e imprima o json desses itens".`
    
* Com isso as primeiras linhas que não fazem parte de `results` foram digamos assim "ignoradas".
    

---

**Avançando ainda mais...**

4- Se continuarmos olhando com atenção, poderemos ver que esse `array` (matriz) `results` possui uma lista de itens, onde:

* a primeira posição do `array` (matriz) é o `index` (índice) `0` e o nome é `Luke Skywalker`
    
* a segunda posição do `array` (matriz) é o `index` (índice) `1` e o nome é o `C-3PO`
    

Então podemos limitar nosso filtro passando como index (índice) `0` e isso nos retornará o nome `Luke Skywalker` como previsto:

```bash
curl https://swapi.dev/api/people | jq '.results[0]'
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663177196208/8MxVlm67B.png align="center")

**Vamos entender o que aconteceu aqui:**

* Adicionamos ao final do nosso comando `| jq '.results[0]'`
    
* Esse `'.results[0]'` é um filtro que estamos dizendo ao jq `"hey, pegue todos os dados do array (matriz) chamada results e imprima o index (índice) 0 (primeira posição da matriz) em um json".`
    
* Com isso o segundo item dessa matriz, no caso o `C-3PO` é digamos assim "ignorado", pois limitamos para o index (índice) `0` em nosso filtro.
    

---

**Avançando mais e mais...**

5- Até agora já descobrimos como chegar nesse valor, mas lembra que queríamos apenas o nome?

Bom, então só precisamos informar essa propriedade para o `jq`:

```bash
curl https://swapi.dev/api/people | jq '.results[0] | .name'
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663177312903/XZPxS0Ggc.png align="center")

<div data-node-type="callout">
<div data-node-type="callout-emoji">☑</div>
<div data-node-type="callout-text"><strong>WOW</strong>, finalmente chegamos lá! 🥳</div>
</div>

Mas aqui vale mais um pouco da sua atenção, vamos dividir nosso comando para entendermos melhor:

* `curl https://swapi.dev/api/people` → faz um `request` para a API do filme Star Wars
    
* `| jq '.results[0]` → filtra os dados do index `0` no array `results`
    
* `| .name'` → imprime na saída a propriedade `name` do index `0` no `array results`
    

Observe que depois do filtro, adicionamos novamente um "`pipe`" `|`, esse último bloco é responsável por "imprimir" as informações para nós como definirmos, isso é a mesma coisa que `stdout`. Grave essa informação, pois ela será útil em todos os próximos comandos, onde vamos mudar e manipular a forma que esses dados serão apresentados para nós.

---

Agora ao invés de listar apenas o nome do index (índice) 0 do array (primeira posição da matriz), vamos listar todos os nomes dessa matriz, para isso é só removermos o 0 de .results\[0\], ficando assim:

```bash
curl https://swapi.dev/api/people | jq '.results[] | .name'
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663177421462/wJePWpyVW.png align="center")

**Vamos entender o que aconteceu aqui:**

* Adicionamos ao final do nosso comando `| jq '.results[] | .name'`
    
* Esse `'.results[] | .name'` é um filtro que estamos dizendo ao jq `"hey, pegue todos os dados do array (matriz) chamada results (ele inteiro sem qualquer índice) e imprima a propriedade name".`
    

---

**Avançando mais, mais e mais...**

6- Legal, já conseguimos listar o nome de todos, mas eles ainda estão digamos assim "jogados", "soltos", vamos consertar isso:

```bash
curl https://swapi.dev/api/people | jq '.results[] | {name: .name}'
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663177514373/bzesrvSld.png align="center")

**Vamos entender o que aconteceu aqui:**

* Adicionamos ao final do nosso comando `| jq '.results[] | {name: .name}'`
    
* Esse `'.results[] | {name: .name}'` é um filtro que estamos dizendo ao jq `"hey, pegue todos os dados do array (matriz) chamada results (ele inteiro sem qualquer índice) e imprima a key (chave) name com o value (valor) da propriedade name entre {}".`
    

---

**Avançando mais, mais, mais e ainda mais...**

7- Estamos melhorando, mas ainda podemos ver que essas informações estão "jogadas", não há formatação `json` e nem vírgulas no final de cada `{}`, vamos consertar isso:

```bash
curl https://swapi.dev/api/people | jq '[.results[] | {name: .name}]'
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663177648143/_O2NF7kE2.png align="center")

**Vamos entender o que aconteceu aqui:**

* A única diferença é que adicionamos colchetes `[]` no início e final do nosso filtro `'[.results[] | {name: .name}]'`
    
* Então estamos dizendo ao jq aqui `"hey coloque o resultado desse filtro dentro de um array (matriz)".`
    

---

**Avançando e avançando...**

8- Até agora vimos exemplos somente com uma propriedade `name`, mas e se quisermos usar várias propriedades juntas? A resposta é simples, separe por vírgulas, por exemplo:

```bash
curl https://swapi.dev/api/people | jq '[.results[] | {name: .name, eye_color: .eye_color}]'
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663177748210/FRKJFxL39.png align="center")

**Vamos entender o que aconteceu aqui:**

* A única diferença é que separamos as propriedades `name` e `eye_color` por vírgulas → ou seja → `'[.results[] | {name: .name, eyecolor: .eye_color}]'`
    
* Então estamos dizendo ao jq aqui `"hey coloque o resultado desse filtro dentro de um array (matriz) com as keys (chaves) name e eye_color com os values (valores) das respectivas propriedades".`
    

---

**Último avanço...**

9- Mas e se já tivermos um valor e quisermos fazer uma pesquisa? Por exemplo queremos montar um novo array (matriz) com os nomes dos personagens que possuem olhos azuis, faremos um `select`:

```bash
curl https://swapi.dev/api/people | jq '[.results[] | select(.eye_color=="blue") | {name: .name}]'
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663177870956/C8ZDmMjIb.png align="center")

**Vamos entender o que aconteceu aqui:**

* A única diferença é que adicionamos `select(.eye_color=="blue")`.
    
* Então estamos dizendo ao jq aqui `"hey vá para a array (matriz) results, ache o value (valor) blue (azul) na propriedade eye_color de cada item e coloque o resultado desse filtro dentro de um array (matriz) com a keys (chave) name com o seu respectivo value (valor).`
    

<div data-node-type="callout">
<div data-node-type="callout-emoji">☑</div>
<div data-node-type="callout-text">E é isso, espero que com essa breve introdução e exemplos, eu possa ter conseguido demonstrar como o <code>jq</code> funciona e como você pode manipular a saída <code>json</code> para suas preferências ou caso de uso.</div>
</div>

---

## Use JQ para Scripts

No seu dia a dia você vai se deparar várias vezes com a necessidade de obter dados de uma saída `json`, mas isso não se aplica somente a sistemas web, você também vai notar que precisará disso principalmente para seus scripts funcionarem corretamente, por exemplo pode ser comum você precisar obter o ID de uma instância na AWS, então para isso você faria:

```bash
aws ec2 describe-instances
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663177990357/rBn3RBP1p.png align="center")

Esse comando do AWS CLI faz uma chamada na API da AWS e te retornaria uma saída `json` com muitas informações, por exemplo:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663178009287/qm8LdWpBj.png align="center")

Mas nós só queremos o ID dessa instância, é aqui que entra o `jq` e tudo que vimos nesse artigo, então bastaria nós retornarmos o valor da key `InstanceID`:

```bash
aws ec2 describe-instances | jq '.Reservations[] | .Instances[] | {Id: .InstanceId}'
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663178064429/diuh3syPc.png align="center")

**Vamos entender o que aconteceu aqui:**

* Adicionamos ao final do nosso comando AWS CLI `| jq '.Reservations[] | .Instances[] | {Id: .InstanceId}'`
    
* `| jq '.Reservations[]` → jq está indo no array `Reservations`
    
* `| .Instances[]` → jq está indo no array `Instances`
    
* `| {Id: .InstanceId}'` → jq está "imprimindo" a key `Id` com o value `InstanceId`
    

E essa informação poderia ser muito útil para um script que agenda o ligar/desligar dessa instância por exemplo.

---

Outro exemplo poderia ser se você estiver usando o AWS ECS Fargate para orquestrar seus contêineres e como parte de um Pipeline automático, você gostaria de fazer o Deploy da sua nova imagem em uma nova Task, para isso seria importante você descobrir o ID dessa Task, então você faria:

```bash
aws ecs list-tasks --cluster <clusterName>
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663178162581/FH0jppWvf.png align="center")

Observe que é retornado um ARN que é o nome completo de um recurso da AWS, mas nós só precisamos do ID que está localizado depois do último `/`, então usaríamos o jq aqui para dividir esses caracteres assim:

```bash
aws ecs list-tasks --cluster <clusterName> | jq -Mr '.taskArns[] | split("/")[-1]'
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1663178218815/lLZlkcQHA.png align="center")

**Vamos entender o que aconteceu aqui:**

* Adicionamos no final do nosso comando AWS CLI `| jq -Mr '.taskArns[] | split("/")[-1]'`
    
* `| jq -Mr '.taskArns[]` → jq está indo para o array `taskArns`
    
* `| split("/")[-1]'` → jq está "imprimindo" o último bloco depois da `/` que é o ID
    

---

## Conclusão

Esses foram alguns exemplos reais e práticos de como usar o `jq` e de como ele pode ser útil no seu dia a dia, obviamente você poderia fazer várias combinações e filtros diferentes e para diferentes ferramentas como inspecionar containers do docker, kubernetes e muitas outras coisas.

<div data-node-type="callout">
<div data-node-type="callout-emoji">✅</div>
<div data-node-type="callout-text">Espero que essas informações tenham sido úteis para você!</div>
</div>
