ProgramaciónDesarrollador Backend Go

¿Cómo se implementa el trabajo con JSON (encoding/json) en Go: características de la serialización, características de las etiquetas struct, dolores frecuentes durante la marshaling/unmarshaling y soluciones alternativas?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

En Go, el marshaling de JSON se implementa por defecto a través del paquete encoding/json. Solo se pueden serializar campos exportados (con letra mayúscula) de las estructuras. Para controlar los nombres y el procesamiento, se utilizan etiquetas struct:

type User struct { ID int `json:"id"` Name string `json:"name,omitempty"` Age int `json:"age,string"` }
  • omitempty excluye el campo cuando su valor es nulo;
  • string serializa el valor como una cadena, incluso si es un número.

Ejemplo de serialización:

user := User{ID: 1, Name: "Oleg"} b, _ := json.Marshal(user) fmt.Println(string(b)) // {"id":1,"name":"Oleg","age":"0"}

Ejemplo de análisis de JSON

var u User json.Unmarshal([]byte('{"id":2,"name":"Ivan"}'), &u)

Pregunta capciosa.

¿Cómo se serializan los campos no exportados (con letra minúscula) de una estructura durante el marshaling a JSON?

Respuesta correcta: Se ignoran, solo participan en la serialización los campos exportados (con letra mayúscula). Esto a menudo rompe la API de manera inesperada:

type Foo struct { bar int // ¡no se serializará! }

Ejemplos de errores reales debido al desconocimiento de los matices del tema.


Historia

El backend devolvía objetos JSON incompletos, ya que parte de los campos necesarios se mantenía no exportada (con letra minúscula). Se tardaron varios días en averiguar por qué los clientes no veían estos campos.


Historia

En la respuesta de la API, el campo contenía la construcción omitempty, pero a veces llegaba un valor vacío, porque el valor nulo para un slice es nil, no un slice vacío. Los clientes recibían null en lugar de un array vacío [] y fallaban al analizar.


Historia

En el proyecto se mezclaban campos dinámicos en las estructuras a través de map[string]interface{}, pero se olvidaban de implementar un UnmarshalJSON personalizado, lo que provocaba que parte de los datos "se perdieran" sin errores. Los datos del cliente se perdían y se recuperaban manualmente a partir de copias de seguridad.