Encoding and Serialization
Overview
Go provides standard encoding packages for JSON, XML, and binary data.
JSON
import "encoding/json"
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
Age int `json:"-"` // Ignored
}
// Encode
user := User{Name: "Alice", Email: "a@b.com"}
data, _ := json.Marshal(user)
// {"name":"Alice","email":"a@b.com"}
// Decode
var u User
json.Unmarshal(data, &u)
// Pretty print
data, _ := json.MarshalIndent(user, "", " ")Streaming JSON
// Encode to writer
encoder := json.NewEncoder(w)
encoder.Encode(user)
// Decode from reader
decoder := json.NewDecoder(r)
decoder.Decode(&user)XML
import "encoding/xml"
type Person struct {
XMLName xml.Name `xml:"person"`
Name string `xml:"name"`
Age int `xml:"age,attr"`
}
data, _ := xml.MarshalIndent(person, "", " ")
xml.Unmarshal(data, &p)Gob (Go Binary)
import "encoding/gob"
// Encode
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
enc.Encode(data)
// Decode
dec := gob.NewDecoder(&buf)
dec.Decode(&result)CSV
import "encoding/csv"
// Write
w := csv.NewWriter(file)
w.Write([]string{"a", "b", "c"})
w.Flush()
// Read
r := csv.NewReader(file)
records, _ := r.ReadAll()Base64
import "encoding/base64"
encoded := base64.StdEncoding.EncodeToString(data)
decoded, _ := base64.StdEncoding.DecodeString(encoded)Summary
| Package | Format |
|---|---|
encoding/json |
JSON |
encoding/xml |
XML |
encoding/gob |
Go binary |
encoding/csv |
CSV |
encoding/base64 |
Base64 |
Worked example
Streaming JSON encode/decode round-trip over an in-memory buffer.
Save as main.go. Then:
go mod init example
go run .package main
import (
"bytes"
"encoding/json"
"fmt"
)
type Event struct {
Type string `json:"type"`
N int `json:"n"`
}
func main() {
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
for i := 1; i <= 3; i++ {
if err := enc.Encode(Event{Type: "tick", N: i}); err != nil {
panic(err)
}
}
dec := json.NewDecoder(&buf)
sum := 0
for dec.More() {
var e Event
if err := dec.Decode(&e); err != nil {
panic(err)
}
sum += e.N
fmt.Printf("event type=%s n=%d\n", e.Type, e.N)
}
fmt.Println("sum:", sum)
}Expected output:
event type=tick n=1
event type=tick n=2
event type=tick n=3
sum: 6
More examples
Tag-driven JSON omitempty + gob preserving unexported-unrelated fields.
package main
import (
"bytes"
"encoding/gob"
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
Score int `json:"score,omitempty"`
}
func main() {
u := User{Name: "Ada", Score: 0} // Score omitted when 0
j, _ := json.Marshal(u)
fmt.Println("json:", string(j))
var buf bytes.Buffer
_ = gob.NewEncoder(&buf).Encode(User{Name: "Ada", Score: 10})
var out User
_ = gob.NewDecoder(&buf).Decode(&out)
fmt.Println("gob score:", out.Score)
}Expected output:
json: {"name":"Ada"}
gob score: 10
Runnable example
Save as main.go. Then:
go mod init example
go run .package main
import (
"bytes"
"encoding/base64"
"encoding/csv"
"encoding/gob"
"encoding/json"
"encoding/xml"
"fmt"
"strings"
)
type User struct {
Name string `json:"name" xml:"name"`
Email string `json:"email,omitempty" xml:"email"`
Age int `json:"-" xml:"-"` // ignored by JSON/XML tags in this demo
}
type PersonXML struct {
XMLName xml.Name `xml:"person"`
Name string `xml:"name"`
Age int `xml:"age,attr"`
}
func main() {
u := User{Name: "Alice", Email: "a@b.com", Age: 30}
// JSON round-trip
j, err := json.Marshal(u)
if err != nil {
panic(err)
}
var u2 User
if err := json.Unmarshal(j, &u2); err != nil {
panic(err)
}
fmt.Println("json:", string(j))
fmt.Println("json name:", u2.Name, "age zeroed:", u2.Age == 0)
// XML round-trip
p := PersonXML{Name: "Bob", Age: 25}
x, err := xml.Marshal(p)
if err != nil {
panic(err)
}
var p2 PersonXML
if err := xml.Unmarshal(x, &p2); err != nil {
panic(err)
}
fmt.Println("xml:", string(x))
fmt.Println("xml age:", p2.Age)
// Gob round-trip (Go-native binary)
var buf bytes.Buffer
if err := gob.NewEncoder(&buf).Encode(u); err != nil {
panic(err)
}
var u3 User
if err := gob.NewDecoder(&buf).Decode(&u3); err != nil {
panic(err)
}
fmt.Println("gob age preserved:", u3.Age)
// CSV
var csvBuf strings.Builder
w := csv.NewWriter(&csvBuf)
_ = w.Write([]string{"name", "email"})
_ = w.Write([]string{u.Name, u.Email})
w.Flush()
records, err := csv.NewReader(strings.NewReader(csvBuf.String())).ReadAll()
if err != nil {
panic(err)
}
fmt.Println("csv rows:", len(records), "data:", records[1])
// Base64
enc := base64.StdEncoding.EncodeToString([]byte("hi"))
dec, _ := base64.StdEncoding.DecodeString(enc)
fmt.Println("b64:", enc, "->", string(dec))
}Expected output:
json: {"name":"Alice","email":"a@b.com"}
json name: Alice age zeroed: true
xml: <person age="25"><name>Bob</name></person>
xml age: 25
gob age preserved: 30
csv rows: 2 data: [Alice a@b.com]
b64: aGk= -> hi
What to notice: json:"-" drops Age from JSON, so it comes back as zero—gob has no tags and preserves the full struct. XML attributes use ,attr. Prefer streaming Encoder/Decoder for large payloads and HTTP bodies.
Try next: Use json.MarshalIndent for pretty output. Stream-decode a JSON array with decoder.Token / decoder.More.