JSON Processing in Go (Golang): From Standard Library to Advanced Tools
JSON (JavaScript Object Notation) is one of the most popular data exchange formats. In Go (Golang), working with JSON is implemented at the highest level thanks to the powerful standard library encoding/json and many third-party tools that speed up and simplify development. In this article, we will take a detailed look at how to serialize, deserialize, validate, and optimize JSON in Go, as well as explore popular libraries that every Go developer should know.
Standard Library encoding/json
encoding/json is a built-in Go package that provides all the necessary functions for working with JSON. Main features:
- Marshaling (serialization) — converting Go structures to a JSON string.
- Unmarshaling (deserialization) — parsing a JSON string into Go structures.
- Stream processing — reading/writing JSON from streams (
io.Reader,io.Writer). - Struct tags — managing field names, skipping empty values, nesting.
Example of Marshaling and Unmarshaling
package main
import ( "encoding/json" "fmt" "log")
type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email"` IsActive bool `json:"is_active"`}
func main() { // Marshaling (struct -> JSON) user := User{ID: 1, Name: "Alexey", Email: "alex@example.com", IsActive: true} jsonData, err := json.Marshal(user) if err != nil { log.Fatal(err) } fmt.Println(string(jsonData)) // Output: {"id":1,"name":"Alexey","email":"alex@example.com","is_active":true}
// Unmarshaling (JSON -> struct) jsonStr := `{"id":2,"name":"Maria","email":"maria@example.com","is_active":false}` var user2 User err = json.Unmarshal([]byte(jsonStr), &user2) if err != nil { log.Fatal(err) } fmt.Printf("%+v", user2) // Output: {ID:2 Name:Maria Email:maria@example.com IsActive:false}}Working with Unstructured Data
Sometimes the JSON structure is unknown in advance. In this case, you can use map[string]interface{} or interface{}:
func main() { jsonStr := `{"name":"Ivan","age":30,"hobbies":["reading","sports"]}` var data map[string]interface{} err := json.Unmarshal([]byte(jsonStr), &data) if err != nil { log.Fatal(err) } fmt.Println(data["name"]) // Ivan fmt.Println(data["hobbies"].([]interface{})[0]) // reading}Popular Third-Party Libraries
Although encoding/json covers most tasks, for high-load systems or specific scenarios, it is worth considering alternatives:
1. easyjson
easyjson is a code generator for fast serialization/deserialization. It creates optimized functions for your structures, providing a 2–5x performance boost compared to the standard library.
- Requires code generation via
easyjson. - Supports custom types and nesting.
- Ideal for microservices with high RPS.
//go:generate easyjson -all user.gotype User struct { ID int `json:"id"` Name string `json:"name"`}
// After generation, use: user.MarshalJSON() / user.UnmarshalJSON()2. gjson
gjson is a library for fast JSON reading without full deserialization. It allows you to get values by path (similar to jq):
import "github.com/tidwall/gjson"
func main() { json := `{"user":{"name":"Olga","age":25}}` name :=