Introduction to Working with JSON in Go
JSON (JavaScript Object Notation) is one of the most popular data exchange formats in modern web applications, microservices, and APIs. The Go language (Golang) offers built-in powerful support for working with JSON through the encoding/json package. This package allows you to easily convert data between Go structures and JSON strings, and vice versa.
In this article, we will thoroughly examine how to perform parsing (deserialization) and serialization of JSON in Go. You will learn how to work with simple and nested structures, handle errors, and configure field names. The material will be useful for both beginners and experienced developers who want to systematize their knowledge.
Basics of Serialization (Marshal) in Go
Converting a Go Structure to JSON
Serialization is the process of converting a Go object (for example, a structure or slice) into a JSON string. The json.Marshal() function is used for this. Let's look at a simple example:
package main
import ( "encoding/json" "fmt")
type User struct { Name string Age int Email string}
func main() { user := User{ Name: "Ivan Petrov", Age: 30, Email: "ivan@example.com", }
jsonData, err := json.Marshal(user) if err != nil { fmt.Println("Serialization error:", err) return }
fmt.Println(string(jsonData))}Program output:
{"Name":"Ivan Petrov","Age":30,"Email":"ivan@example.com"}Note: the field names in JSON match the field names of the structure. But it is often necessary to change them, for example, to use camelCase style. For this, struct tags are used.
Using Tags to Configure JSON
Struct tags allow you to specify exactly how a field will be serialized. Let's add tags to our example:
type User struct { Name string `json:"name"` Age int `json:"age"` Email string `json:"email,omitempty"`}Now the output will be:
{"name":"Ivan Petrov","age":30,"email":"ivan@example.com"}Key tag options:
json:"field_name"— sets the field name in JSON.omitempty— excludes the field from JSON if it has a zero value (empty string, 0, false, nil).-— completely ignores the field during serialization/deserialization.
Serialization of Slices and Maps
The encoding/json package works well not only with structures, but also with slices, maps, and simple types:
// Slice of structuresusers := []User{ {Name: "Anna", Age: 25}, {Name: "Boris", Age: 35},}jsonUsers, _ := json.Marshal(users)fmt.Println(string(jsonUsers))// Output: [{"name":"Anna","age":25},{"name":"Boris","age":35}]
// Mapdata := map[string]interface{}{ "status": "ok", "count": 42,}jsonMap, _ := json.Marshal(data)fmt.Println(string(jsonMap))// Output: {"count":42,"status":"ok"}Parsing JSON (Unmarshal) in Go
Basic Parsing into a Structure
Deserialization (parsing) is the reverse process: converting a JSON string into a Go object. The json.Unmarshal() function is used. Important: the target structure must be exported (fields with capital letters) or have appropriate tags.
jsonString := `{"name":"Maria","age":28,"email":"maria@example.com"}`
var user Usererr := json.Unmarshal([]byte(jsonString), &user)if err != nil { fmt.Println("Parsing error:", err) return}
fmt.Printf("Name: %s, Age: %d", user.Name, user.Age)// Output: Name: Maria, Age: 28Parsing Nested Structures
JSON often contains nested objects.