Use the encoding/json package's Marshal function to convert Go data structures into JSON byte slices, or MarshalIndent if you need pretty-printed output with indentation. Remember that Marshal returns an error, so always check it before using the resulting bytes.
Here is a standard example using a struct with proper JSON tags to control field names and omit empty values:
package main
import (
"encoding/json"
"fmt"
"log"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email,omitempty"` // Omit if empty
}
func main() {
user := User{ID: 1, Name: "Alice", Email: ""}
// Encode to bytes
data, err := json.Marshal(user)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
// Output: {"id":1,"name":"Alice"}
}
If you need the JSON formatted for human readability (e.g., for logging or debugging), use json.MarshalIndent instead. This function takes a prefix string and an indent string to control the formatting:
package main
import (
"encoding/json"
"fmt"
"log"
)
type Config struct {
Debug bool `json:"debug"`
Host string `json:"host"`
Port int `json:"port"`
}
func main() {
cfg := Config{Debug: true, Host: "localhost", Port: 8080}
// Encode with indentation
data, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
// Output:
// {
// "debug": true,
// "host": "localhost",
// "port": 8080
// }
}
Key things to keep in mind:
- Tags are optional but recommended: Without
json:"fieldName"tags, Go uses the struct field name in lowercase. Tags allow you to map to camelCase or other formats required by APIs. - Error handling is mandatory:
Marshalcan fail if the data contains unsupported types (like channels or functions) or circular references. Never ignore the error return. - Output is a byte slice: The result is
[]byte, not a string. Convert it withstring(data)only when printing or logging; keep it as bytes if writing to a file or network stream to avoid unnecessary copying. - Special types: Go automatically handles maps, slices, and pointers. If a pointer is
nil, the field is omitted unless you use theomitemptytag logic differently or handle it explicitly.