Lecciones del módulo (5/5)
encoding/json
encoding/json es el paquete canónico para serializar estructuras Go a JSON y viceversa. Conocer sus convenciones y trampas le ahorra horas de depuración de API y archivos de configuración.
Mariscal y Desmariscal
Las dos funciones principales:
data, err := json.Marshal(v) // Go → []byte JSON
err = json.Unmarshal(data, &v) // JSON → Go (pass a pointer!)type User struct {
Name string
Email string
}
u := User{Name: "Ada", Email: "ada@example.com"}
b, _ := json.Marshal(u)
fmt.Println(string(b))
// {"Name":"Ada","Email":"ada@example.com"}
var back User
_ = json.Unmarshal(b, &back)Para resultados con sangría (legible por humanos), utilice json.MarshalIndent(v, "", " ").
Solo campos exportados
json.Marshal serializa sólo campos exportados (mayúsculas). Los campos privados se ignoran silenciosamente:
type U struct {
Name string // exported → serialized
age int // private → ignored
}Etiquetas de estructura: control de nombre y opciones
Las etiquetas json:"..." controlan el nombre, la omisión y los tipos en la salida:
type User struct {
Name string `json:"name"` // rename
Email string `json:"email,omitempty"` // omit if zero value
Private string `json:"-"` // never serialized
ID int `json:"id,string"` // number as string
}Opciones más utilizadas:
,omitempty: omite el campo si es valor cero (0, "", nulo, sector/mapa vacío).,-: nunca serializado/deserializado.,string: envuelve números/booles como cadenas (útil para ID de JS).
Decodificador/Codificador para transmisiones
Cuando trabaje con io.Reader/io.Writer (cuerpo HTTP, archivos grandes), use Decoder y Encoder en lugar de cargar todo en la memoria:
dec := json.NewDecoder(resp.Body)
var users []User
if err := dec.Decode(&users); err != nil {
return err
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
_ = enc.Encode(users)Decoder también admite dec.Token() para transmitir análisis pieza por pieza y dec.DisallowUnknownFields() para rechazar JSON con claves inesperadas (útil para la validación de entradas).
Mapas genéricos y any
Si no conoce el esquema, deserialice en map[string]any:
var v map[string]any
_ = json.Unmarshal(data, &v)
fmt.Println(v["name"])Los valores tendrán tipos dinámicos (string, float64 para números, []any, map[string]any, bool, nil).
Errores comunes
- Olvidando
&:json.Unmarshal(data, v)no completa nada; necesitas&v. - Decodificación de estructuras con campos nulos: para evitar pánicos, verifique
errANTES de leer los campos. - Tipos incompatibles: deserializar un número en una cadena o viceversa devuelve
*json.UnmarshalTypeError.
Ejercicios
Serializa la estructura u a JSON con json.Marshal e imprime el resultado como una cadena.
Solución disponible después de 3 intentos
Deserialice `{"Name":"Ada"}` en la estructura U con json.Unmarshal e imprímalo.
Solución disponible después de 3 intentos
¿El campo `name string` (minúscula) de una estructura está incluido en json.Marshal?
type U struct {
name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))