Lección 17 · 17 de 20
encoding/json y etiquetas de struct · Go
Convierta structs a JSON y de vuelta en Go con json.Marshal y json.Unmarshal, y controle los nombres con etiquetas como omitempty y -.

El paquete `encoding/json` convierte structs en JSON y JSON en structs. Solo tiene en cuenta los campos exportados (los que empiezan por mayúscula), y el nombre de cada uno en el JSON lo decide su etiqueta: el texto entre comillas invertidas, como json:"sku". Sin etiqueta se usaría el nombre del campo tal cual, SKU.
Dos opciones de etiqueta muy útiles: `omitempty` omite el campo si tiene el valor cero (por eso el primer pedido sale sin note) y `-` no lo escribe nunca, ideal para datos internos como el margen, Margin. Los structs anidados y los slices (Items) se convierten solos.
`json.Marshal(out)` devuelve []byte y un error; string(data) lo convierte en texto para escribirlo. Los campos salen en el orden del struct.
`json.Unmarshal` hace lo contrario y necesita un puntero, &in, para poder rellenar el struct. Las claves que el struct no tiene, como coupon, se ignoran sin error, y las que faltan dejan el valor cero. Al emparejar claves no distingue mayúsculas y minúsculas.
Si un tipo no encaja, "nine" donde se espera un int, Unmarshal devuelve un error que dice exactamente qué campo falla. `json.MarshalIndent` escribe el JSON con sangría, más fácil de leer: el segundo argumento es un prefijo para cada línea y el tercero, la sangría.
Código · main.go
package mainimport ( "encoding/json" "fmt")type Item struct { SKU string `json:"sku"` Qty int `json:"qty"`}type Order struct { ID int `json:"id"` Customer string `json:"customer"` Items []Item `json:"items"` Note string `json:"note,omitempty"` // left out when empty Margin int `json:"-"` // never encoded}func main() { out := Order{ID: 7, Customer: "Ana Ruiz", Items: []Item{{"KB-01", 1}, {"MS-02", 2}}, Margin: 30} data, err := json.Marshal(out) fmt.Println(string(data), err) input := `{"id": 8, "customer": "Luis Gil", "items": [{"sku": "CB-03", "qty": 4}], "note": "gift", "coupon": "X"}` var in Order err = json.Unmarshal([]byte(input), &in) // pass a pointer so it can fill the struct fmt.Printf("%+v %v\n", in, err) // unknown keys such as coupon are ignored err = json.Unmarshal([]byte(`{"id": "nine"}`), &in) fmt.Println("error:", err) pretty, _ := json.MarshalIndent(in.Items[0], "", " ") fmt.Println(string(pretty))}Salida · go run main.go
{"id":7,"customer":"Ana Ruiz","items":[{"sku":"KB-01","qty":1},{"sku":"MS-02","qty":2}]} <nil>
{ID:8 Customer:Luis Gil Items:[{SKU:CB-03 Qty:4}] Note:gift Margin:0} <nil>
error: json: cannot unmarshal string into Go struct field Order.id of type int
{
"sku": "CB-03",
"qty": 4
}Para recordar
- Solo se codifican los campos exportados (en mayúscula).
json:"nombre"fija el nombre de la clave.omitemptyomite los valores cero;-omite el campo siempre.Unmarshalnecesita un puntero y devuelve un error si un tipo no encaja.- Las claves desconocidas se ignoran.
Ejercicio
Añada al struct Order un campo Paid bool con la etiqueta json:"paid", póngalo a true en el primer pedido y añada "paid": false al JSON de entrada. Compruebe qué sale en cada Println.