# JSON With Struct Tags — Go (Golang)

Source: https://www.skillbyai.com/en/go/s-json

> Marshal and unmarshal safely.

## Tags control field names and omission

`encoding/json` maps exported struct fields to JSON. **Struct tags** set names (`json:"customer"`), skip empty values (`omitempty`), or exclude fields (`json:"-"`); unexported fields are always ignored. Unknown JSON keys are ignored by default (use a Decoder with `DisallowUnknownFields` to reject them), and type mismatches return descriptive errors. Validate decoded data before using it.

## Tags, ignored fields and a type error, run

I ran this with Go 1.27.1 (`go run .` in a module named demo, standard library only). Marshalling omits empty Items, the "-" tagged Notes and the unexported field. Unmarshalling ignores the unknown "extra" key; a string for the numeric id returns a clear error.

```go
package main

import (
	"encoding/json"
	"fmt"
)

type Order struct {
	ID       int      `json:"id"`
	Customer string   `json:"customer"`
	Items    []string `json:"items,omitempty"`
	Notes    string   `json:"-"` // never serialised
	internal string   // unexported: ignored by encoding/json
}

func main() {
	o := Order{ID: 7, Customer: "Asha", Notes: "secret", internal: "x"}
	b, _ := json.Marshal(o)
	fmt.Println(string(b))

	var in Order
	err := json.Unmarshal([]byte(`{"id": 8, "customer": "Ravi", "items": ["pen"], "extra": true}`), &in)
	fmt.Printf("%+v err=%v\n", in, err)

	err = json.Unmarshal([]byte(`{"id": "eight"}`), &in)
	fmt.Println("type error:", err)
}
```

Output:

```
{"id":7,"customer":"Asha"}
{ID:8 Customer:Ravi Items:[pen] Notes: internal:} err=<nil>
type error: json: cannot unmarshal string into Go struct field Order.id of type int
```

## Reject unknown fields in APIs

For request bodies, a json.Decoder with DisallowUnknownFields catches typos in client payloads.

**Quiz:** What does the tag json:"-" do?

- [ ] Encrypts it
- [ ] Makes the field required
- [ ] Renames it to "-"
- [x] Excludes the field from JSON encoding and decoding

*Answer:* Excludes the field from JSON encoding and decoding. Keep internal fields out of payloads.
