JSON Processing in Go (Golang): From Basics to Advanced Techniques
Go (Golang) offers a powerful and intuitive set of tools for working with JSON. The standard library encoding/json covers 95% of tasks, and for high-load projects, there are more performant alternatives. In this article, we will cover all aspects of JSON processing in Go: from basic serialization to custom parsers and optimization.
1. Basics: The Standard Library encoding/json
In Go, JSON is processed through the encoding/json package. The main operations are marshaling (serialization to JSON) and unmarshaling (deserialization from JSON).
1.1. Marshaling (struct → JSON)
To convert a Go struct to JSON, use the json.Marshal() function:
package main
import ( "encoding/json" "fmt" "log")
type User struct { Name string `json:"name"` Age int `json:"age"` Email string `json:"email,omitempty"` // omitempty - skip if empty}
func main() { user := User{ Name: "Ivan Petrov", Age: 30, Email: "ivan@example.com", }
jsonData, err := json.Marshal(user) if err != nil { log.Fatal(err) }
fmt.Println(string(jsonData)) // {"name":"Ivan Petrov","age":30,"email":"ivan@example.com"}}Important: Struct fields must be exported (start with a capital letter). The json:"fieldname" tags control the field names in JSON.
1.2. Unmarshaling (JSON → struct)
For the reverse transformation, use json.Unmarshal():
func main() { jsonString := `{"name":"Anna","age":25,"email":"anna@mail.com"}` var user User err := json.Unmarshal([]byte(jsonString), &user) if err != nil { log.Fatal(err) }
fmt.Printf("Name: %s, Age: %d", user.Name, user.Age) // Name: Anna, Age: 25}2. Working with Nested Structures and Arrays
JSON often contains nested objects and arrays. In Go, this maps to nested structs and slices:
type Address struct { City string `json:"city"` Street string `json:"street"` ZipCode string `json:"zip_code"`}
type Company struct { Name string `json:"name"` Employees []User `json:"employees"` Address Address `json:"address"`}
func main() { companyJSON := `{ "name": "TechCorp", "employees": [ {"name":"Oleg","age":28,"email":"oleg@tech.com"}, {"name":"Maria","age":32,"email":"maria@tech.com"} ], "address": { "city": "Moscow", "street": "Tverskaya, 10", "zip_code": "101000" } }`
var company Company json.Unmarshal([]byte(companyJSON), &company) fmt.Printf("Company: %s, City: %s, Employees: %d", company.Name, company.Address.City, len(company.Employees))}3. Advanced Techniques
3.1. Custom Serialization (Marshaler/Unmarshaler Interfaces)
Sometimes you need to control how a type is converted to JSON. To do this, implement the json.Marshaler and json.Unmarshaler interfaces:
type CustomTime struct { time.Time}
const layout = "2006-01-02T15:04:05Z"
func (ct CustomTime) MarshalJSON() ([]byte, error) { return json.Marshal(ct.Format(layout))}
func (ct *CustomTime) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } t, err := time.Parse(layout, s) if err != nil { return err } ct.Time = t return nil}
type Event struct { Title string `json:"title"` Date CustomTime `js Also in library
Working with Images in PHP: resize, crop
Swift WebSocket Libraries: Starscream and URLSessionWebSocketTask
JavaScript Application Configuration (Node.js): dotenv, convict, nconf Libraries