Saltar al contenido principal
eLearner.app
Módulo 8 · Lección 5 de 540/50 en el curso~14 min
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:

Go
data, err := json.Marshal(v)      // Go → []byte JSON
err = json.Unmarshal(data, &v)    // JSON → Go (pass a pointer!)
Go
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:

Go
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:

Go
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:

Go
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:

Go
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 err ANTES de leer los campos.
  • Tipos incompatibles: deserializar un número en una cadena o viceversa devuelve *json.UnmarshalTypeError.

Ejercicios

Ejercicio#go.m8.l5.e1
Intentos: 0Cargando...

Serializa la estructura u a JSON con json.Marshal e imprime el resultado como una cadena.

Cargando editor...

Solución disponible después de 3 intentos

Ejercicio#go.m8.l5.e2
Intentos: 0Cargando...

Deserialice `{"Name":"Ada"}` en la estructura U con json.Unmarshal e imprímalo.

Cargando editor...

Solución disponible después de 3 intentos

Cuestionario#go.m8.l5.e3
Listo

¿El campo `name string` (minúscula) de una estructura está incluido en json.Marshal?

Go
type U struct {
  name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))
Opciones de respuesta