Procesamiento de JSON en Go (Golang): guía completa
Go (Golang) es un lenguaje de programación compilado moderno, desarrollado en Google. Una de sus fortalezas es el soporte integrado para el formato JSON a través del paquete estándar encoding/json. A diferencia de muchos otros lenguajes donde se requiere instalar bibliotecas de terceros, en Go el procesamiento de JSON está disponible "de fábrica" y se caracteriza por su alto rendimiento y tipado estricto.
En este artículo, analizaremos en detalle todos los aspectos del trabajo con JSON en Go: desde el análisis simple hasta escenarios complejos con tipos personalizados y procesamiento por flujos.
Fundamentos: codificación y decodificación de JSON
El paquete encoding/json proporciona dos funciones principales: json.Marshal() para serializar estructuras de Go a JSON y json.Unmarshal() para deserializar JSON de vuelta a estructuras.
Ejemplo: serialización de una estructura a JSON
package main
import ( "encoding/json" "fmt")
type User struct { Name string `json:"name"` Age int `json:"age"` Email string `json:"email,omitempty"`}
func main() { user := User{ Name: "Iván Petrov", Age: 30, Email: "ivan@example.com", }
jsonData, err := json.Marshal(user) if err != nil { fmt.Println("Error de serialización:", err) return }
fmt.Println(string(jsonData)) // Salida: {"name":"Iván Petrov","age":30,"email":"ivan@example.com"}}Ejemplo: deserialización de JSON a una estructura
func main() { jsonString := `{"name":"Ana Smirnova","age":25,"email":"anna@example.com"}` var user User err := json.Unmarshal([]byte(jsonString), &user) if err != nil { fmt.Println("Error de deserialización:", err) return }
fmt.Printf("Nombre: %s, Edad: %d, Email: %s", user.Name, user.Age, user.Email)}Etiquetas de estructura (Struct Tags)
Las etiquetas de estructura en Go permiten controlar cómo se serializarán los campos a JSON. Este es un mecanismo potente para personalizar nombres de campos, omitir valores vacíos y otras opciones.
Opciones principales de etiquetas:
json:"name"— establece el nombre del campo en JSONjson:"-"— excluye completamente el campo del JSONjson:"name,omitempty"— omite el campo si contiene un valor cero (0, "", false, nil)json:"name,string"— convierte forzosamente un campo numérico a cadena
Ejemplo con varias etiquetas:
type Product struct { ID int `json:"id"` Title string `json:"title"` Description string `json:"description,omitempty"` Price float64 `json:"price,string"` SecretKey string `json:"-"`}
func main() { product := Product{ ID: 101, Title: "Portátil", Description: "", Price: 899.99, SecretKey: "sk-12345", }
jsonData, _ := json.MarshalIndent(product, "", " ") fmt.Println(string(jsonData)) // Salida: // { // "id": 101, // "title": "Portátil", // "price": "899.99" // }}Trabajo con datos JSON arbitrarios (interface{})
A veces la estructura de los datos JSON no se conoce de antemano. En tales casos, se puede usar el tipo interface{} o map[string]interface{}.
func main() { jsonString := `{"name":"Prueba","values":[1,2,3],"active":true,"metadata":{"version":2}}` var data map[string]interface{} err := json.Unmarshal([]byte(jsonString), &data) if err != nil { fmt.Println("Error:", err) return }
// Acceso a valores con conversión de tipos name := data["name"].(string) values := data["values"].([]interface{})