Cómo ocultar campos de estructura en JSON: Go para principiantes y profesionales

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

La magia de JSON en Go: ¿por qué unos campos son visibles y otros no?

\n

¿Alguna vez se ha encontrado con una situación en la que su estructura de Go envía en la respuesta JSON algo que el cliente no necesita ver? Por ejemplo, la contraseña de un usuario, el ID interno de la base de datos o una clave secreta. O, por el contrario, necesita mostrar un campo solo bajo una condición determinada (por ejemplo, si no está vacío).

\n

Este problema es uno de los más populares en Stack Overflow, y con razón. Trabajar con JSON en Go es un arte de equilibrio entre el rigor de los tipos y la flexibilidad de la representación. Hoy analizaremos todas las formas: desde la simple etiqueta json:"-" hasta soluciones personalizadas complejas con interfaces. ¡Allá vamos!

\n\n

1. La forma más sencilla: la etiqueta json:"-"

\n

Go permite controlar la serialización de una estructura mediante etiquetas especiales. Si desea ocultar permanentemente un campo del JSON, simplemente agregue json:"-".

\n
type User struct {\n    Name     string `json:"name"`\n    Password string `json:"-"`\n    Age      int    `json:"age"`\n}\n\nfunc main() {\n    u := User{Name: "Alicia", Password: "supersecret", Age: 30}\n    data, _ := json.Marshal(u)\n    fmt.Println(string(data))\n    // Salida: {"name":"Alicia","age":30}\n}
\n

El campo Password desapareció como si nunca hubiera existido. Ideal para datos confidenciales que nunca deben salir del servidor.

\n\n

2. Ocultación condicional: omitempty

\n

A veces es necesario ocultar un campo solo si está vacío. Para esto se utiliza la opción omitempty (abreviatura de "omit if empty").

\n
type Product struct {\n    Name        string  `json:"name"`\n    Description string  `json:"description,omitempty"`\n    Price       float64 `json:"price,omitempty"`\n}\n\nfunc main() {\n    p1 := Product{Name: "Libro", Price: 500.0}\n    data1, _ := json.Marshal(p1)\n    fmt.Println(string(data1)) // {"name":"Libro","price":500}\n\n    p2 := Product{Name: "Curso"}\n    data2, _ := json.Marshal(p2)\n    fmt.Println(string(data2)) // {"name":"Curso"}\n}
\n

Importante: omitempty solo funciona con valores "cero": "", 0, false, nil (para slices, maps, punteros).

\n\n

Trampa con campos numéricos

\n

Tenga cuidado: si Price es igual a 0, también se ocultará. En algunas lógicas de negocio esto no es aceptable (un producto gratuito también es un precio). En tales casos, es mejor usar punteros.

\n\n

3. Uso de punteros (*) e interfaces

\n

Los punteros son su mejor amigo cuando necesita distinguir entre "valor no especificado" y "valor igual a cero".

\n
type UserProfile struct {\n    Name    string  `json:"name"`\n    Age     *int    `json:"age,omitempty"`  // puntero a int\n    Bio     *string `json:"bio,omitempty"`\n}\n\nfunc main() {\n    // Edad no especificada — el campo se oculta\n    u1 := UserProfile{Name: "Juan"}\n    data1, _ := json.Marshal(u1)\n    fmt.Println(string(data1)) // {"name":"Juan"}\n\n    // Edad = 0 — es un valor significativo\n    zero := 0\n    u2 := UserProfile{Name: "María", Age: &zero}\n    data2, _ := json.Marshal(u2)\n    fmt.Println(string(data2)) // {"name":"María","age":0}\n}
\n

Este enfoque se usa a menudo en APIs REST, donde es necesario actualizar solo los campos enviados (actualización parcial, solicitudes PATCH).

\n\n

4. Serialización personalizada: la interfaz json.Marshaler

\n

Si las etiquetas estándar no son suficientes, puede controlar completamente el proceso. Implemente la interfaz json.Marshaler y escriba su propia lógica.

\n
type DynamicUser struct {\n    ID        int\n    Name      string\n    ShowEmail bool\n    Email     string\n}\n\nfunc (u DynamicUser) MarshalJSON() ([]byte, error) {\n    // Creamos una estructura anónima solo para la serialización\n    m := map[string]interface{}{\n        "id":   u.ID,\n        "name": u.Name,\n    }\n    if u.ShowEmail {                

Blogs

Book Recommendations