Manipulando JSON e XML em Linguagem Go

Manipulando JSON e XML em Linguagem Go

Um homem de óculos e suéter está sentado à mesa, concentrado em seu laptop.

Descubra como criar e converter Structs em Go para JSON ou XML. Aprenda a manipular dados facilmente com exemplos práticos.

Tempo de Leitura: 5 minutos

Olá. Dando continuidade ao artigo anterior, hoje irei abordar a criação de Structs em Go e como podemos, facilmente, converter seus dados para saídas em JSON ou XML.

Para aqueles que já vem da linguagem C já está acostumado com esse tipo de abordagem.

Definição de Struct:

Em Go, uma "struct" (abreviação de structure) é um tipo de dados composto que agrupa campos de dados com tipos diferentes sob um único nome. As structs são uma maneira de criar tipos de dados personalizados e mais complexos, organizando dados relacionados em uma única unidade. Uma struct em Go envolve usar a palavra-chave type seguida pelo nome da struct, uma lista de campos e seus tipos associados. Aqui está um exemplo simples:

package main

import "fmt"

// Definição de uma struct chamada "Pessoa"
type Pessoa struct {
    Nome  string
    Idade int
    Sexo  string
}

func main() {
    // Criando uma instância da struct "Pessoa"
    pessoa1 := Pessoa{
        Nome:  "João",
        Idade: 25,
        Sexo:  "Masculino",
    }

    // Acessando os campos da struct
    fmt.Println("Nome:", pessoa1.Nome)
    fmt.Println("Idade:", pessoa1.Idade)
    fmt.Println("Sexo:", pessoa1.Sexo)
}

Ao executar o retorno será:

  • Nome: João
  • Idade: 25
  • Sexo: Masculino

Fácil né?

Conheça nosso manifesto

Vamos fazer nesse exemplo retornar um JSON e após um XML, para isso precisamos definir algumas modificações na nossa estrutura.

Agoram, vamos nomear cada propriedade da estrutura a nomenclatura que ficará o JSON, ex.:

// Definição de uma struct chamada "Pessoa"
type Pessoa struct {
    Nome  string `json:"nome"`
    Idade int    `json:"idade"`
    Sexo  string `json:"sexo"`
}

Isso é importante para que o programa entenda qual os elementos que compõem o JSON tanto na entrada quanto na saída dos dados.

Finalizando vamos usar a biblioteca JSON, nativa no Go, importando a biblioteca "encoding/json" e usar o método Marshal. 

O código ficará assim:

package main

import (
    "encoding/json"
    "fmt"
)

// Definição de uma struct chamada "Pessoa"
type Pessoa struct {
    Nome  string `json:"nome"`
    Idade int    `json:"idade"`
    Sexo  string `json:"sexo"`
}

func main() {
    // Criando uma instância da struct "Pessoa"
    pessoa1 := Pessoa{
        Nome:  "João",
        Idade: 25,
        Sexo:  "Masculino",
    }

    // Criando o arquivo JSON a partir de pessoa1
    jsonData, err := json.Marshal(&pessoa1)
    if err != nil {
        fmt.Println(err.Error())
    }

    // Acessando JSON da struct
    fmt.Println(string(jsonData))

}

Após executar você terá o retorno:

{"nome":"João","idade":25,"sexo":"Masculino"}

Com poucas linhas de código conseguimos retornar um JSON com os dados passados para a nossa estrutura. 

Agora digamos que precisamos que seja retornado um XML desses dados, a maneira é bem similar.

Mas para definir um retorno em XML utilizaremos a biblioteca "encoding/xml" e criar algumas alterações em nossa estrutura para o XML receber um atributo e que as suas tags fiquem corretas:

// Definição de uma struct chamada "Pessoa"
type Pessoa struct {
    XMLName xml.Name `xml:"pessoa"`
    Tipo    string   `xml:"tipo,attr"`
    Nome    string   `xml:"nome"`
    Idade   int      `xml:"idade"`
    Sexo    string   `xml:"sexo"`
}

Então o código ficará assim:

package main

import (
    "encoding/xml"
    "fmt"
)

// Definição de uma struct chamada "Pessoa"
type Pessoa struct {
    XMLName xml.Name `xml:"pessoa"`
    Tipo    string   `xml:"tipo,attr"`
    Nome    string   `xml:"nome"`
    Idade   int      `xml:"idade"`
    Sexo    string   `xml:"sexo"`
}

func main() {
    // Criando uma instância da struct "Pessoa"
    pessoa1 := Pessoa{
        Tipo:  "Pessoa1",
        Nome:  "João",
        Idade: 25,
        Sexo:  "Masculino",
    }

// Criando o arquivo XML a partir de pessoa1
    xmlData, err := xml.Marshal(&pessoa1)
    if err != nil {
        fmt.Println(err.Error())
    }

    // Acessando XML da struct
    fmt.Println(string(xmlData))

}

Ao executar terá o seguinte retorno:

<pessoa tipo="Pessoa1">
<nome>João</nome><idade>25</idade><sexo>Masculino</sexo>
</pessoa>

A diferença é que foram criadas uma tag para a entidade pessoa e mais um atributo para informar a Pessoa1.

Agora vamos fazer o contrário.
Enviaremos um JSON e depois enviar um XML, quando enviados eles terão que alimentar a nossa estrutura e ela irá devolver os atributos.

Para isso, tanto o JSON quanto o XML irão usar o método Unmarshal das suas respectivas bibliotecas.

Exemplo com o XML:

package main

import (
    "encoding/xml"
    "fmt"
)

// Definição de uma struct chamada "Pessoa"
type Pessoa struct {
    XMLName xml.Name `xml:"pessoa"`
    Tipo    string   `xml:"tipo,attr"`
    Nome    string   `xml:"nome"`
    Idade   int      `xml:"idade"`
    Sexo    string   `xml:"sexo"`
}

func main() {

    // Criando uma variavel pessoa1 da Struct Pessoa
    var pessoa1 Pessoa

    //Passando o XML em uma variavel;

    xmlData := `<pessoa tipo="Pessoa1"><nome>João</nome><idade>25</idade><sexo>Masculino</sexo></pessoa>`

    //passando os dados do XML para a pessoa1
    if err := xml.Unmarshal([]byte(xmlData), &pessoa1); err != nil {
        fmt.Println(err.Error())
    }

    // Acessando os campos da struct
    fmt.Println("Nome:", pessoa1.Nome)
    fmt.Println("Idade:", pessoa1.Idade)
    fmt.Println("Sexo:", pessoa1.Sexo)

}

Ao executar terá o seguinte retorno:

  • Nome: João
  • Idade: 25
  • Sexo: Masculino

Com os dados vindo de um XML, aqui passei via string, mas poderia vir de um arquivo, alimentou a nossa estrutura e alimentou as suas propriedades.
O mesmo com JSON, só devemos fazer algumas mudanças de biblioteca e a chamada na struct Pessoa:

package main

import (
    "encoding/json"
    "fmt"
)

// Definição de uma struct chamada "Pessoa"
type Pessoa struct {
    Nome  string `json:"nome"`
    Idade int    `json:"idade"`
    Sexo  string `json:"sexo"`
}

func main() {

    // Criando uma variavel pessoa1 da Struct Pessoa
    var pessoa1 Pessoa

    //Passando o JSON em uma variavel;

    jsonData := `{"nome":"João","idade":25,"sexo":"Masculino"}`

    //passando os dados do JSON para a pessoa1
    if err := json.Unmarshal([]byte(jsonData), &pessoa1); err != nil {
        fmt.Println(err.Error())
    }

    // Acessando os campos da struct
    fmt.Println("Nome:", pessoa1.Nome)
    fmt.Println("Idade:", pessoa1.Idade)
    fmt.Println("Sexo:", pessoa1.Sexo)

}

Novamente passei direto pela propriedade string, mas poderá ser enviada de um arquivo também. E no final teremos o mesmo resultado:

  • Nome: João
  • Idade: 25
  • Sexo: Masculino

Para finalizar esse artigo, agora teremos a seguinte situação. Vamos passar um JSON e retornar um XML e depois passar um XML e retornar um JSON. Isso é interessante para quem precisar fazer conversões entre esses dois tipos de arquivos.

JSON para XML:

package main

import (
    "encoding/json"
    "encoding/xml"
    "fmt"
)

// Definição de uma struct chamada "Pessoa"
type Pessoa struct {
    xml.Name `json:"-" xml:"pessoa"`
    Tipo     string `json:"tipo" xml:"tipo,attr"`
    Nome     string `json:"nome" xml:"nome"`
    Idade    int    `json:"idade" xml:"idade"`
    Sexo     string `json:"sexo" xml:"sexo"`
}

func main() {

    // Criando uma variavel pessoa1 da Struct Pessoa
    var pessoa1 Pessoa

    //Passando o JSON em uma variavel;

    jsonData := `{"tipo":"Pessoa1","nome":"João","idade":25,"sexo":"Masculino"}`

    //passando os dados do JSON para a pessoa1
    if err := json.Unmarshal([]byte(jsonData), &pessoa1); err != nil {
        fmt.Println(err.Error())
    }

    // Criando o arquivo XML a partir de pessoa1
    xmlData, err := xml.Marshal(&pessoa1)
    if err != nil {
        fmt.Println(err.Error())
    }

    // Acessando XML da struct
    fmt.Println(string(xmlData))

}

Retorno:

<pessoa tipo="Pessoa1">

<nome>João</nome><idade>25</idade><sexo>Masculino</sexo>

</pessoa>

XML para JSON:

package main

import (
    "encoding/json"
    "encoding/xml"
    "fmt"
)

// Definição de uma struct chamada "Pessoa"
type Pessoa struct {
    xml.Name `json:"-" xml:"pessoa"`
    Tipo     string `json:"tipo" xml:"tipo,attr"`
    Nome     string `json:"nome" xml:"nome"`
    Idade    int    `json:"idade" xml:"idade"`
    Sexo     string `json:"sexo" xml:"sexo"`
}

func main() {
    // Criando uma variavel pessoa1 da Struct Pessoa
    var pessoa1 Pessoa
    //Passando o XML em uma variavel;
    xmlData := `<pessoa tipo="Pessoa1"><nome>João</nome><idade>25</idade><sexo>Masculino</sexo></pessoa>`

    //passando os dados do XML para a pessoa1
    if err := xml.Unmarshal([]byte(xmlData), &pessoa1); err != nil {
        fmt.Println(err.Error())
    }
    // Criando o arquivo JSON a partir de pessoa1
    jsonData, err := json.Marshal(&pessoa1)
    if err != nil {
        fmt.Println(err.Error())
    }
    // Acessando JSON da struct
    fmt.Println(string(jsonData))

}

Retorno:

{"tipo":"Pessoa1","nome":"João","idade":25,"sexo":"Masculino"}

Esse foi um exemplo bem simples de como utilizar, manipular dados de JSON e XML e de conversão de dados. Existem várias opções de utilizar essa abordagem, mas tentei criar uma maneira mais fácil de como entender a trabalhar com esses arquivos.

Fico por aqui, agradeço quem leu até o final e seguiu os exemplos, aguardem para mais próximos artigos.

Thiago Alves
Thiago Alves
Graduado em Analise e Desenvolvimento de Sistemas. Pós graduação em Engenharia de Software. Líder técnico da equipe DFE Desktop na Tecnospeed. "Delpheiro" de coração e entusiasta nas ferramentas low-code e no-code

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.

Pular para o conteúdo