DEV Community

Cover image for Trabalhando com Json e Go
.·. Felipe Paz .·.
.·. Felipe Paz .·.

Posted on

Trabalhando com Json e Go

Pra mim que vim do javascript onde o json é algo tão "banal", entender o funcionamento com Go foi um tanto quanto diferente.

O Go tem uma pegada muito grande com ponteiros e bytes, então, de primeiro momento, é meio cabuloso saber que uma variável que foi passada como parâmetro vai ter o retorno da função diretamente no local da memória em que ela foi alocada e por aí vai.

Em javascript, uma estrutura do tipo:

{
  "campo": "qualquer coisa",
  "numero": 10
}
Enter fullscreen mode Exit fullscreen mode

é entendível na hora, contudo, em Go, a coisa não é bem assim.

Bora ver um exemplo prático e eu vou detalhar coisa por coisa.

package main

import (
    "encoding/json"
    "fmt"
)

type Car struct {
    Color string `json:"color"`
    Model string `json:"model"`
}

func main() {
    car := Car{"Black", "Lancer"}

    b, err := json.Marshal(car)

    if err != nil {
        fmt.Println(err)
    }

    fmt.Println(string(b))
}

Enter fullscreen mode Exit fullscreen mode

Explicando:

package main
Enter fullscreen mode Exit fullscreen mode

estou definindo que o conteúdo dese arquivo pertence ao pacote main. Por exemplo, se eu tivesse uma estrutura

app
   services
       main.go
   controllers
       main.go
       users.go
   main.go
Enter fullscreen mode Exit fullscreen mode

Eu poderia dizer que services/main.go pertence ao pacote services, portanto, package services, controllers/main.go e controllers/users.go ao pacote controllers e por aí vai. Mas enfim, a ideia aqui é explicar json com go, outros detalhes eu vou abordar em outro capítulo. Prossigamos ...

type Car struct {
    Color string `json:"color"`
    Model string `json:"model"`
}
Enter fullscreen mode Exit fullscreen mode

Aqui eu estou "definindo o meu objeto". Não sei se seria a melhor comparação, mas sabe o Type do typescript? Quase isso! Diferença que aqui eu consigo passar esse cara como ponteiro e trabalhar diretamente nele.

func main() {
    car := Car{"Black", "Lancer"}
//  car := Car{
//    Color: "Black",
//    Model: "Lancer",
//  }
        ...
Enter fullscreen mode Exit fullscreen mode

Aqui eu to dizendo: cria a varíavel car e atribui à ela o tipo Car com os seguintes valores ....
Note que existem duas maneiras de atribuir uma struct à uma variável. Pode ser parecido como é em javascript, ou passar os valores diretamente na struct sem precisar inserir as chaves. Em structs mais simples é até viável, mas pensa num negócio gigante passar os valores sem saber o que é o que.

Ah, só uma observação: isso := é diferente de =.
No primeiro, eu estou criando a variável e reservando ela em memória, ou seja, dando vida à ela e lhe atribuindo um valor,
enquanto que no segundo, a variável já existe em memória e eu estou reatribuindo um valor à ela. 0.o

Continuando ...

Aqui o bicho pega

b, err := json.Marshal(car)

if err != nil {
   fmt.Println(err)
}

fmt.Println(string(b))
Enter fullscreen mode Exit fullscreen mode

O go pode trazer mais de um retorno numa função. Uma espécie de tupla, por assim dizer.

E também em Go, as chamadas de funções geralmente são o nome do pacote e a função. No nosso exemplo, estamos chamando do pacote json a função Marshal.

A função Marshal retorna dois resultados: um slice de bytes (é praticamente um array mas sem limite como um array) e um erro. Como parâmetro, essa função espera uma variável do tipo struct que no nosso caso é car.

Logo após é feita a checagem pra garantir que não houve algum erro (lembrando que o foco aqui é json e não tratativas de erros, uso correto da linguagem nem nada).

E depois, por último, convertemos aqueles bytes em uma string para ser mostrado pelo Println, nosso console.log do Go.

E pah, a saída que teremos vai ser

{"color":"Black","model":"Lancer"}
Enter fullscreen mode Exit fullscreen mode

Outras observações cabulosas do Go:

Quando se define uma struct, as "chaves" dela, para serem lidas por qualquer função ou algo do tipo, precisam ser em letras maiúsculas. Portanto, se eu tivesse:

type Car struct {
    color string `json:"color"`
    model string `json:"model"`
}
Enter fullscreen mode Exit fullscreen mode

a saída seria simplesmente

{}
Enter fullscreen mode Exit fullscreen mode

uma vez que os atributos dessa struct não foram exportados (implicitamente escrever iniciando em letra minúscula fala pro Go que o atributo daquela struct não é para ser exportado).

Mas fica estranho né, imagina uma api que esteja esperando esse objeto:

{
   "color": "black",
   "model": "Lancer"
}
Enter fullscreen mode Exit fullscreen mode

mas estamos enviando "Color" e "Model" no body da request.

Para resolver isso, colocamos aquele json:"color" na frente do atributo da struct. Com isso estamos dizendo para o Go: Cara, a struct Car tem o atributo Color, então, internamente, a gente referencia Color mas externamente, ou seja, se formos enviar esse json pra fora do programa ou vamos receber esse json de algum outro lugar, ele vai ter o campo "color" e não "Color".

É, isso é Go ...

Essa é a primeira parte, transformando uma struct em um json. Vamos ter a segunda parte onde vamos transformar um json em uma struct.

Te espero lá!!!

Oldest comments (0)