Trabajo con JSON en Go: análisis y serialización de datos

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

Introducción al Trabajo con JSON en Go

JSON (Notación de Objetos JavaScript) es un formato ligero de intercambio de datos ampliamente utilizado en aplicaciones web, APIs y microservicios. El lenguaje Go (Golang) proporciona una potente biblioteca integrada encoding/json que facilita el análisis (deserialización) y la serialización de datos. En este artículo, examinaremos a fondo cómo trabajar con JSON en Go, cubriendo las funciones principales, estructuras y mejores prácticas.



Fundamentos de Serialización y Deserialización

La serialización es el proceso de convertir una estructura de datos de Go (por ejemplo, un struct o slice) en una cadena JSON. La deserialización es el proceso inverso: convertir JSON en una estructura de Go.



Serialización (Marshal)

Para la serialización se utiliza la función json.Marshal(). Toma un valor de Go y devuelve un segmento de bytes ([]byte) con la representación JSON.

package main

import ( "encoding/json" "fmt")

type User struct { Name string `json:"name"` Age int `json:"age"` Email string `json:"email,omitempty"`}

func main() { user := User{Name: "Alexey", Age: 30, Email: "alex@example.com"} jsonData, err := json.Marshal(user) if err != nil { fmt.Println("Serialization error:", err) return } fmt.Println(string(jsonData)) // Output: {"name":"Alexey","age":30,"email":"alex@example.com"}

Observe las etiquetas json:"field_name". Permiten controlar los nombres de las claves en JSON, así como agregar opciones como omitempty (omitir el campo si está vacío).



Deserialización (Unmarshal)

Para analizar JSON en una estructura de Go se utiliza la función json.Unmarshal(). Toma un segmento de bytes y un puntero a la estructura donde se deben escribir los datos.

func main() {    jsonString := `{"name":"Maria","age":25,"email":"maria@example.com"}`    var user User    err := json.Unmarshal([]byte(jsonString), &user)    if err != nil {        fmt.Println("Parsing error:", err)        return    }    fmt.Printf("Name: %s, Age: %d, Email: %s", user.Name, user.Age, user.Email)}

Importante: la estructura debe estar predefinida y sus campos deben corresponder a las claves JSON (teniendo en cuenta las etiquetas).



Trabajo con Objetos JSON Arbitrarios

A veces la estructura JSON no se conoce de antemano o es demasiado compleja. En tales casos, se puede usar map[string]interface{} o interface{}.



Uso de map[string]interface{}

func main() {    jsonString := `{"name":"Ivan","age":35,"address":{"city":"Moscow","street":"Lenina"}}`    var result map[string]interface{}    err := json.Unmarshal([]byte(jsonString), &result)    if err != nil {        fmt.Println("Error:", err)        return    }    fmt.Println(result["name"]) // Ivan    fmt.Println(result["age"])  // 35 (type float64)    // For nested objects, type assertion is needed    address := result["address"].(map[string]interface{})    fmt.Println(address["city"]) // Moscow}

La desventaja de este enfoque es la necesidad de una aserción de tipo manual (.(map[string]interface{})), lo que puede causar un pánico si los tipos no coinciden.



Uso de json.RawMessage

Si necesita diferir el análisis de parte del JSON, utilice json.RawMessage. Esto le permite primero analizar la estructura principal y luego procesar los datos anidados por separado.

type Response struct {    Status string          `json:"status"`    Data   json.RawMessage `json:"data"`}

func main() { jsonString := `{"status":"ok","data":{"user":"Peter","score":100}}` var resp Response json.Unmarshal([]byte(jsonString), &resp)

// Now Data can be parsed separately var userData map[string]interface{} json.Unm

Blogs

Book Recommendations