16 Mapeando Propiedades JSON en Go
Published Jun 24, 2024
🧠 Introducción
En un mundo ideal, todos usaríamos el mismo estándar para nombrar campos: camelCase
, snake_case
, o al menos sin espacios. Pero no vivimos en ese mundo 😅
En la práctica, cuando consumes un API externo o trabajas con archivos JSON variados, te puedes encontrar cosas como:
{ "updated at": "06/06/2024", "ID": "1", "nombre": "uva" }
Y si no lo manejas bien, tu aplicación puede romperse.
1. 🎯 ¿Cómo se hace el mapeo de campos en Go?
Sabemos que para mapear un JSON a un struct usamos json.Unmarshal
. Pero si los nombres de los campos no coinciden exactamente, no se asignarán.
Ejemplo:
type Product struct {
Id string
Name string
UpdatedAt string
}
Y el JSON:
{
"id": "1",
"name": "grapes",
"updated at": "06/06/2024"
}
Accederás correctamente a id
y name
, pero UpdatedAt
estará vacío. ¿Por qué? Porque "updated at" ≠ "UpdatedAt".
2. 🛠️ Solución: Tags en campos del struct
Para mapear nombres no estándar del JSON a campos Go, usamos etiquetas:
type Product struct {
Id string `json:"id"`
Name string `json:"name"`
UpdatedAt string `json:"updated at"`
}
Ahora el unmarshalling asigna correctamente incluso campos con espacios, mayúsculas, u otros formatos.
3. 🌪️ ¿Y si el JSON es muy dinámico o no sabemos su estructura?
Si no queremos (o no podemos) definir un struct, usamos:
map[string]interface{}
Eso nos da la flexibilidad de acceder a cualquier campo del JSON como si fuera un map
.
Ejemplo:
jsonString := `{
"name":"ElprogramadorGT",
"eye_color":"brown",
"gender":"male",
"movies":{
"The Matrix":1999,
"Interstellar":2014,
"Parasite":2019
}
}`
var result map[string]interface{}
json.Unmarshal([]byte(jsonString), &result)
fmt.Println(result["movies"])
result["movies"] es una interface{}, así que no puedes acceder directamente a "Parasite" sin un type assertion.
4. 🧠 Type Assertion: accediendo a datos anidados
Go no hace castings automáticos. Si necesitas acceder a "Parasite"
:
movies := result["movies"].(map[string]interface{})
fmt.Println(movies["Parasite"]) // 2019
Así le estás diciendo: “Confío en que esto es un map dentro del map”.
⚠️ Si el tipo no coincide, Go lanza panic. Puedes hacer un type assertion seguro con:
if movies, ok := result["movies"].(map[string]interface{}); ok {
fmt.Println(movies["Parasite"])
}
✅ Conclusión
- JSON no siempre viene con campos bien nombrados o estandarizados.
- En Go, usamos tags en structs (
json:"campo_json"
) para mapear correctamente los datos. - Para datos dinámicos o muy variables, puedes usar
map[string]interface{}
. - Go requiere type assertions para acceder a campos anidados dentro de
interface{}
.
🛠️ Práctica recomendada
- Crea un struct
Person
con campos como"first name"
y"birth year"
, y usa tags para mapearlos. - Carga un JSON dinámico con
map[string]interface{}
que incluya al menos un objeto anidado. - Accede a los campos anidados usando type assertion.
- Implementa una verificación segura (
if ok
) para evitar errores si la estructura cambia.
🚀 Siguientes pasos
- 🔁 Aprende a codificar structs a JSON usando
json.Marshal
(inverso aUnmarshal
). - 🧱 Combina structs + maps para escenarios mixtos.
- 🌐 Integra JSON decoding en una API real con
net/http
.