Introduction to Working with JSON in Go
\n\nJSON (JavaScript Object Notation) is one of the most popular data interchange formats in modern web applications and microservices. Due to its simplicity and readability, JSON has become the standard for REST APIs, configuration files, and storing structured data.
\n\nThe Go language (Golang) offers built-in powerful support for JSON through the encoding/json package. This package allows you to easily convert Go structures to JSON (serialization) and back (deserialization or parsing).
In this article, we will cover the basics of working with JSON in Go: from simple examples to handling complex nested structures and errors. The material is aimed at beginner developers who are already familiar with the basics of Go syntax.
\n\nSerialization: Converting Go Structures to JSON
\n\nSerialization (encoding) is the process of converting data from Go's internal representation (structures, slices, maps) into a JSON string. In Go, the json.Marshal() function is used for this.
Basic Serialization Example
\n\npackage main\n\nimport (\n "encoding/json"\n "fmt"\n)\n\ntype Person struct {\n Name string\n Age int\n City string\n}\n\nfunc main() {\n person := Person{\n Name: "Ivan Petrov",\n Age: 30,\n City: "Moscow",\n }\n\n jsonBytes, err := json.Marshal(person)\n if err != nil {\n fmt.Println("Serialization error:", err)\n return\n }\n\n fmt.Println(string(jsonBytes))\n // Output: {"Name":"Ivan Petrov","Age":30,"City":"Moscow"}\n}\n\nNote: json.Marshal() returns a byte slice ([]byte), so we convert it to a string using string().
Formatted Output with json.MarshalIndent
\n\nFor debugging or readable output, use json.MarshalIndent():
jsonBytes, err := json.MarshalIndent(person, "", " ")\nif err != nil {\n fmt.Println("Error:", err)\n return\n}\nfmt.Println(string(jsonBytes))\n// Output:\n// {\n// "Name": "Ivan Petrov",\n// "Age": 30,\n// "City": "Moscow"\n// }\n\nSerializing Slices and Maps
\n\nGo allows serializing not only structures but also other data types:
\n\n// Slice of structures\npeople := []Person{\n {Name: "Anna", Age: 25, City: "SPb"},\n {Name: "Peter", Age: 35, City: "Kazan"},\n}\njsonBytes, _ := json.Marshal(people)\nfmt.Println(string(jsonBytes))\n// Output: [{"Name":"Anna","Age":25,"City":"SPb"},{"Name":"Peter","Age":35,"City":"Kazan"}]\n\n// Map\nscores := map[string]int{"Algebra": 5, "Physics": 4, "Computer Science": 5}\njsonBytes, _ = json.Marshal(scores)\nfmt.Println(string(jsonBytes))\n// Output: {"Algebra":5,"Computer Science":5,"Physics":4}\n\nJSON Parsing: Converting JSON to Go Structures
\n\nParsing (deserialization) is the reverse process: from a JSON string we obtain a Go structure. The json.Unmarshal() function is used for this.
Parsing into a Structure
\n\npackage main\n\nimport (\n "encoding/json"\n "fmt"\n)\n\ntype Person struct {\n Name string\n Age int\n City string\n}\n\nfunc main() {\n jsonString := `{"Name":"Ivan Petrov","Age":30,"City":"Moscow"}`\n\n var person Person\n err := json.Unmarshal([]byte(jsonString), &person)\n if err != nil {\n fmt.Println("Parsing error:", err)\n return\n }\n\n fmt.Printf("Name: %s, Age: %d, City: %s\\n", person.Name, person.Age, person.City)\n // Output: Name: Ivan Petrov, Age: 30, City: Moscow\n}\n\nImportant: pass a pointer to the structure (&person), otherwise Unmarshal will not be able to modify its fields.
Parsing into map[string]interface{}
\n\nIf the data structure is not known in advance, you can use a generic type:
\n\njsonString := `{"name":"Anna","