En Go no hace falta instalar nada extra: el paquete encoding/json de la biblioteca estándar permite serializar (Go → JSON) y deserializar (JSON → Go).
package main
import (
"encoding/json"
"fmt"
)
type Producto struct {
Codigo int `json:"codigo"`
Descripcion string `json:"descripcion"`
Precio float64 `json:"precio"`
Disponible bool `json:"disponible"`
Tags []string `json:"tags"`
}
func main() {
prod := Producto{
Codigo: 101,
Descripcion: "Teclado mecánico",
Precio: 1200.50,
Disponible: true,
Tags: []string{"periférico", "oferta"},
}
// Convertir struct a JSON
jsonData, err := json.Marshal(prod)
if err != nil {
panic(err)
}
fmt.Println(string(jsonData))
// {"codigo":101,"descripcion":"Teclado mecánico","precio":1200.5,"disponible":true,"tags":["periférico","oferta"]}
}
👉 json.Marshal()
convierte un struct Go en []byte
con el JSON.
jsonPretty, err := json.MarshalIndent(prod, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(jsonPretty))
// Salida con sangría
package main
import (
"encoding/json"
"fmt"
)
type Producto struct {
Codigo int `json:"codigo"`
Descripcion string `json:"descripcion"`
Precio float64 `json:"precio"`
Disponible bool `json:"disponible"`
Tags []string `json:"tags"`
}
func main() {
jsonString := `{
"codigo": 102,
"descripcion": "Mouse inalámbrico",
"precio": 850.75,
"disponible": false,
"tags": ["periférico"]
}`
var prod Producto
// Convertir JSON → struct
if err := json.Unmarshal([]byte(jsonString), &prod); err != nil {
panic(err)
}
fmt.Println(prod.Descripcion) // Mouse inalámbrico
fmt.Println(prod.Precio) // 850.75
}
👉 json.Unmarshal()
convierte JSON ([]byte
) en un struct Go.
package main
import (
"encoding/json"
"fmt"
)
type Producto struct {
Codigo int `json:"codigo"`
Descripcion string `json:"descripcion"`
Precio float64 `json:"precio"`
}
func main() {
jsonString := `[
{"codigo": 201, "descripcion": "Monitor 24 pulgadas", "precio": 1500.00},
{"codigo": 202, "descripcion": "Notebook", "precio": 2500.50}
]`
var productos []Producto
if err := json.Unmarshal([]byte(jsonString), &productos); err != nil {
panic(err)
}
for _, p := range productos {
fmt.Printf("%d - %s ($%.2f)\n", p.Codigo, p.Descripcion, p.Precio)
}
}
package main
import (
"encoding/json"
"fmt"
"os"
)
type Usuario struct {
Nombre string `json:"nombre"`
Edad int `json:"edad"`
Activo bool `json:"activo"`
}
func main() {
usuario := Usuario{"María", 29, true}
// Guardar en archivo
file, err := os.Create("usuario.json")
if err != nil {
panic(err)
}
defer file.Close()
encoder := json.NewEncoder(file)
encoder.SetIndent("", " ") // salida legible
if err := encoder.Encode(usuario); err != nil {
panic(err)
}
// Leer desde archivo
file2, err := os.Open("usuario.json")
if err != nil {
panic(err)
}
defer file2.Close()
var usuarioLeido Usuario
decoder := json.NewDecoder(file2)
if err := decoder.Decode(&usuarioLeido); err != nil {
panic(err)
}
fmt.Println("Usuario leído:", usuarioLeido.Nombre, usuarioLeido.Edad)
}
Cuando no conocemos la estructura exacta del JSON, podemos usar un mapa genérico:
package main
import (
"encoding/json"
"fmt"
)
func main() {
jsonString := `{"codigo": 301, "extra": {"color": "negro", "stock": 20}}`
var data map[string]interface{}
if err := json.Unmarshal([]byte(jsonString), &data); err != nil {
panic(err)
}
fmt.Println(data["codigo"]) // 301
extra := data["extra"].(map[string]interface{})
fmt.Println(extra["color"]) // negro
}
json.Marshal()
— Go struct → JSON ([]byte
).json.Unmarshal()
— JSON ([]byte
) → Go struct.MarshalIndent
/ Encoder.SetIndent
— salida legible.json:"campo"
para mapear nombres de propiedades.map[string]interface{}
.