Go ofrece soporte integrado para la codificación y
decodificación de JSON, incluyendo para tipos de datos
integrados y personalizados.
|
|
|
package main
|
|
import (
"encoding/json"
"fmt"
"os"
)
|
Usaremos estas dos estructuras para demostrar la codificación y
decodificación de tipos personalizados a continuación.
|
type response1 struct {
Page int
Fruits []string
}
|
Solo los campos exportados serán codificados/decodificados en JSON.
Los campos deben comenzar con letras mayúsculas para ser exportados.
|
type response2 struct {
Page int `json:"page"`
Fruits []string `json:"fruits"`
}
|
|
func main() {
|
Primero veremos la codificación de tipos de datos básicos a
cadenas JSON. Aquí hay algunos ejemplos para valores atómicos.
|
bolB, _ := json.Marshal(true)
fmt.Println(string(bolB))
|
|
intB, _ := json.Marshal(1)
fmt.Println(string(intB))
|
|
fltB, _ := json.Marshal(2.34)
fmt.Println(string(fltB))
|
|
strB, _ := json.Marshal("gopher")
fmt.Println(string(strB))
|
Y aquí hay algunos para slices y mapas, que se codifican
en arreglos y objetos JSON como esperarías.
|
slcD := []string{"apple", "peach", "pear"}
slcB, _ := json.Marshal(slcD)
fmt.Println(string(slcB))
|
|
mapD := map[string]int{"apple": 5, "lettuce": 7}
mapB, _ := json.Marshal(mapD)
fmt.Println(string(mapB))
|
El paquete JSON puede codificar automáticamente tus
tipos de datos personalizados. Solo incluirá campos exportados
en la salida codificada y por defecto
usará esos nombres como las claves JSON.
|
res1D := &response1{
Page: 1,
Fruits: []string{"apple", "peach", "pear"}}
res1B, _ := json.Marshal(res1D)
fmt.Println(string(res1B))
|
Puedes usar etiquetas en las declaraciones de campos de estructuras
para personalizar los nombres de las claves JSON codificadas. Revisa la
definición de response2 arriba para ver un ejemplo
de tales etiquetas.
|
res2D := &response2{
Page: 1,
Fruits: []string{"apple", "peach", "pear"}}
res2B, _ := json.Marshal(res2D)
fmt.Println(string(res2B))
|
Ahora veamos la decodificación de datos JSON en valores de Go.
Aquí hay un ejemplo para una estructura de datos genérica.
|
byt := []byte(`{"num":6.13,"strs":["a","b"]}`)
|
Necesitamos proporcionar una variable donde el paquete JSON
pueda poner los datos decodificados. Este
map[string]interface{} contendrá un mapa de cadenas
a tipos de datos arbitrarios.
|
var dat map[string]interface{}
|
Aquí está la decodificación real y una verificación de
errores asociados.
|
if err := json.Unmarshal(byt, &dat); err != nil {
panic(err)
}
fmt.Println(dat)
|
Para usar los valores en el mapa decodificado,
necesitaremos convertirlos a su tipo apropiado.
Por ejemplo, aquí convertimos el valor en num al
tipo float64 esperado.
|
num := dat["num"].(float64)
fmt.Println(num)
|
Acceder a datos anidados requiere una serie de
conversiones.
|
strs := dat["strs"].([]interface{})
str1 := strs[0].(string)
fmt.Println(str1)
|
También podemos decodificar JSON en tipos de datos personalizados.
Esto tiene las ventajas de agregar seguridad de tipo adicional
a nuestros programas y eliminar la
necesidad de afirmaciones de tipo al acceder a los datos
decodificados.
|
str := `{"page": 1, "fruits": ["apple", "peach"]}`
res := response2{}
json.Unmarshal([]byte(str), &res)
fmt.Println(res)
fmt.Println(res.Fruits[0])
|
En los ejemplos anteriores siempre usamos bytes y
cadenas como intermediarios entre los datos y
la representación JSON en la salida estándar. También podemos
transmitir codificaciones JSON directamente a os.Writer s como
os.Stdout o incluso cuerpos de respuesta HTTP.
|
enc := json.NewEncoder(os.Stdout)
d := map[string]int{"apple": 5, "lettuce": 7}
enc.Encode(d)
}
|