ZetCode

Go JSON

last modified August 24, 2023

Go JSON tutorial shows how to work with JSON data in Golang.

$ go version
go version go1.18.1 linux/amd64

We use Go version 1.18.

JSON

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easily read and written by humans and parsed and generated by machines. The application/json is the official Internet media type for JSON. The JSON filename extension is .json.

The encoding/json package implements encoding and decoding of JSON.

Go encode to JSON

The Marshal function encodes data to JSON.

encoding.go
package main

import (
    "encoding/json"
    "fmt"
    "log"
)

type User struct {
    Id         int
    Name       string
    Occupation string
}

func main() {

    u1 := User{1, "John Doe", "gardener"}

    json_data, err := json.Marshal(u1)

    if err != nil {

        log.Fatal(err)
    }

    fmt.Println(string(json_data))

    users := []User{
        {Id: 2, Name: "Roger Roe", Occupation: "driver"},
        {Id: 3, Name: "Lucy Smith", Occupation: "teacher"},
        {Id: 4, Name: "David Brown", Occupation: "programmer"},
    }

    json_data2, err := json.Marshal(users)

    if err != nil {

        log.Fatal(err)
    }

    fmt.Println(string(json_data2))
}

In the code example, we transform a Go struct and a slice of structs into JSON format.

type User struct {
    Id         int
    Name       string
    Occupation string
}

We declare the User struct.

u1 := User{1, "John Doe", "gardener"}

We create the struct instance.

json_data, err := json.Marshal(u1)

We encode the u1 struct into JSON with Marshal.

fmt.Println(string(json_data))

Since json_data is a byte array, we convert it to a string with the string function.

users := []User{
    {Id: 2, Name: "Roger Roe", Occupation: "driver"},
    {Id: 3, Name: "Lucy Smith", Occupation: "teacher"},
    {Id: 4, Name: "David Brown", Occupation: "programmer"},
}

We have a slice of users.

json_data2, err := json.Marshal(users)

We encode the slice of users with Marshal.

fmt.Println(string(json_data2))

We print the encoded slice.

$ go run encoding.go 
{"Id":1,"Name":"John Doe","Occupation":"gardener"}
[{"Id":2,"Name":"Roger Roe","Occupation":"driver"},{"Id":3,"Name":"Lucy Smith","Occupation":"teacher"},
{"Id":4,"Name":"David Brown","Occupation":"programmer"}]

Go decode to JSON

The Unmarshal function decodes JSON data into Go values.

decoding.go
package main

import (
    "encoding/json"
    "fmt"
    "log"
)

type User struct {
    Id         int
    Name       string
    Occupation string
}

func main() {

    var u1 User

    data := []byte(`{
        "Id" : 1,
        "Name": "John Doe",
        "Occupation": "gardener"
    }`)

    err := json.Unmarshal(data, &u1)

    if err != nil {

        log.Fatal(err)
    }

    fmt.Println("Struct is:", u1)
    fmt.Printf("%s is a %s.\n", u1.Name, u1.Occupation)

    var u2 []User

    data2 := []byte(`
    [
        {"Id":2,"Name":"Roger Roe","Occupation":"driver"},
        {"Id":3,"Name":"Lucy Smith","Occupation":"teacher"},
        {"Id":4,"Name":"David Brown","Occupation":"programmer"}
    ]`)

    err2 := json.Unmarshal(data2, &u2)

    if err2 != nil {

        log.Fatal(err2)
    }

    for i := range u2 {

        fmt.Println(u2[i])
    }
}

We decode a JSON string into a Go struct and a slice of structs.

data := []byte(`{
    "Id" : 1,
    "Name": "John Doe",
    "Occupation": "gardener"
}`)

We have a JSON object which is transformed into bytes.

err := json.Unmarshal(data, &u1)

We decode the u1 struct from JSON into a struct with Unmarshal.

var u2 []User

We declare a slice of User structs.

data2 := []byte(`
[
    {"Id":2,"Name":"Roger Roe","Occupation":"driver"},
    {"Id":3,"Name":"Lucy Smith","Occupation":"teacher"},
    {"Id":4,"Name":"David Brown","Occupation":"programmer"}
]`)

This is a JSON array to be decoded into a Go slice.

err2 := json.Unmarshal(data2, &u2)

We decode the JSON array to Go slice with Unmarshal.

for i := range u2 {

    fmt.Println(u2[i])
}

We print the decoded JSON array user by user.

$ go run decoding.go 
Struct is: {1 John Doe gardener}
John Doe is a gardener.
{2 Roger Roe driver}
{3 Lucy Smith teacher}
{4 David Brown programmer}

Go JSON pretty print

The output can be pretty-printed with the MarshalIndent function.

pretty_print.go
package main

import (
    "encoding/json"
    "fmt"
    "log"
)

func main() {

    birds := map[string]interface{}{
        "sounds": map[string]string{
            "pigeon":  "coo",
            "eagle":   "squak",
            "owl":     "hoot",
            "duck":    "quack",
            "cuckoo":  "ku-ku",
            "raven":   "cruck-cruck",
            "chicken": "cluck",
            "rooster": "cock-a-doodle-do",
        },
    }

    data, err := json.MarshalIndent(birds, "", "    ")

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(data))
}

In the code example, we have a map of bird sounds. The output is prettified with MarshalIndent.

$ go run pretty_print.go 
{
    "sounds": {
        "chicken": "cluck",
        "cuckoo": "ku-ku",
        "duck": "quack",
        "eagle": "squak",
        "owl": "hoot",
        "pigeon": "coo",
        "raven": "cruck-cruck",
        "rooster": "cock-a-doodle-do"
    }
}

We can see that the output is indented and hence more readable.

Go JSON read from file

The next example reads JSON data from a file.

data.json
[
    {
        "name": "John Doe",
        "occupation": "gardener",
        "born": "1992-03-02"
    },
    {
        "name": "Brian Flemming",
        "occupation": "teacher",
        "born": "1967-11-22"
    },
    {
        "name": "Lucy Black",
        "occupation": "accountant",
        "born": "1995-04-07"
    },
    {
        "name": "John Doe",
        "occupation": "gardener",
        "born": "1972-08-30"
    }
]

This is the data.json file.

read_file.go
package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "os"
)

type User struct {
    Name       string
    Occupation string
    Born       string
}

func main() {

    filename, err := os.Open("data.json")
    if err != nil {
        log.Fatal(err)
    }

    defer filename.Close()

    data, err := ioutil.ReadAll(filename)

    if err != nil {
        log.Fatal(err)
    }

    var result []User

    jsonErr := json.Unmarshal(data, &result)

    if jsonErr != nil {
        log.Fatal(jsonErr)
    }

    fmt.Println(result)
}

The example reads JSON data from a file and decodes it to a slice of user structs.

$ go run read_json.go 
[{John Doe gardener 1992-03-02} {Brian Flemming teacher 1967-11-22} 
 {Lucy Black accountant 1995-04-07} {John Doe gardener 1972-08-30}]

Go JSON HttpClient

The net/http package provides HTTP client and server implementations.

astros.go
package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "time"
)

type Astronaut struct {
    Name  string
    Craft string
}

type people struct {
    Number  int
    People  []Astronaut
    Message string
}

func main() {

    url := "http://api.open-notify.org/astros.json"

    var netClient = http.Client{
        Timeout: time.Second * 10,
    }

    res, err := netClient.Get(url)

    if err != nil {
        log.Fatal(err)
    }

    defer res.Body.Close()

    body, err := ioutil.ReadAll(res.Body)

    fmt.Println(body)

    if err != nil {
        log.Fatal(err)
    }

    astros := people{}

    jsonErr := json.Unmarshal(body, &astros)

    if jsonErr != nil {
        log.Fatal(jsonErr)
    }

    fmt.Println(astros)
}

The example reads data from a web service using the built-in Go HTTP client. We create a GET request to a service, which returns data about astronauts of the International Space Station.

$ go run astros.go 
{3 [{Chris Cassidy ISS} {Anatoly Ivanishin ISS} {Ivan Vagner ISS}] success}

At this moment, there are three astronauts on the space station.

In this article we have worked with JSON in Golang.

Author

My name is Jan Bodnar and I am a passionate programmer with many years of programming experience. I have been writing programming articles since 2007. So far, I have written over 1400 articles and 8 e-books. I have over eight years of experience in teaching programming.

List all Go tutorials.