JSON in go

Priyansh SaoPriyansh Sao
5 min read

JSON (JavaScript Object Notation) is a lightweight data format used to store and exchange data between a client and a server.

Go provides the encoding/json package to easily work with JSON data.

Marshalling:

package main

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

func main() {

    // Marshalling
    myMap := map[string]interface{}{
        "name":    "John",
        "Class":   9,
        "over18": false,
        "subjects": map[string]interface{}{
            "marks": []int{23, 23, 44, 43},
        },
    }

    jsonData, err := json.Marshal(myMap)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(jsonData))
}

Adding Time :
You can also store the current time in JSON. Go will convert it into a proper format.

//Using time
    myTimeMap := map[string]interface{}{
        "TimeNow": time.Now(),
    }

    jsonTimeData, err := json.Marshal(myTimeMap)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(jsonTimeData))

Struct without JSON tags :
When using structs without tags, Go uses field names as JSON keys. But note:

The field must start with a capital letter to be exported (visible for JSON encoding).

// Using Struct with no Json tags
    type Student struct { //remember the struct to be decoded or encoded should be exported
        Name   string
        Class  int
        Over18 bool
        Marks  []int
    }

    S1 := &Student{
        Name:   "John",
        Class:  9,
        Over18: false,
        Marks:  []int{22, 34, 42, 40},
    }

    jsonStructData, err := json.Marshal(S1)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(jsonStructData))

Struct with JSON tags :
Adding JSON tags lets you control the key names in the final JSON. For example:

  • Over18 field will appear as "over18" in JSON.
//using structs with explicit json tags
    type NewStudent struct { //remember the struct to be decoded or encoded should be exported
        Name   string `json:"name"`
        Class  int    `json:"class"`
        Over18 bool   `json:"over18"`
        Marks  []int  `json:"marks"`
    }
    S2 := &NewStudent{
        Name:   "John",
        Class:  9,
        Over18: false,
        Marks:  []int{22, 34, 42, 40},
    }

    jsonStructWTData, err := json.Marshal(S2)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(jsonStructWTData))

Using omitempty to hide empty fields :

If the Marks slice is nil or empty, it will be skipped from the JSON output. This keeps the output clean.

// using omit empty for omitting empty fields

    type NewStudent1 struct { //remember the struct to be decoded or encoded should be exported
        Name   string `json:"name"`
        Class  int    `json:"class"`
        Over18 bool   `json:"over18"`
        Marks  []int  `json:"marks,omitempty"`
    }
    S3 := &NewStudent1{
        Name:   "John",
        Class:  9,
        Over18: false,
        Marks:  nil,
    }

    jsonStructWTData, err = json.Marshal(S3)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(jsonStructWTData))

Decoding JSON into a map[string]interface{} :

Unmarshal is the opposite of Marshal.
Unmarshal = Convert JSON → Go

// Parsing JSON data into map
    jsondata := 
                    `{
                        "name":"John",
                        "class": 9,
                        "over18": false,
                        "marks":[22,34,54,65]
                    }`

    var anotherMap map[string] interface{}

    err = json.Unmarshal([]byte(jsondata), &anotherMap)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(anotherMap)

Decoding JSON into a struct :

It converts the JSON into a proper Go struct.

    // Parsing json into struct
    var myStruct NewStudent

    err = json.Unmarshal([]byte(jsondata), &myStruct)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(myStruct)

Writing JSON to Stdout using Encoder :

Instead of printing JSON manually, you can directly encode and write it to the terminal (or any output stream) using an Encoder.

// encoding struct data to json and writing it to stdout
    enc := json.NewEncoder(os.Stdout)
    enc.Encode(S2)

Reading JSON from a file using Decoder :

// decoding json data from a file "ex.json" to a struct
    file, _ := os.Open("ex.json") 
    defer file.Close()

    dec := json.NewDecoder(file)
    dec.Decode(&myStruct)
    fmt.Println(myStruct)

complete code:

package main

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

func main() {

    // Marshalling
    myMap := map[string]interface{}{
        "name":    "John",
        "Class":   9,
        "over18": false,
        "subjects": map[string]interface{}{
            "marks": []int{23, 23, 44, 43},
        },
    }

    jsonData, err := json.Marshal(myMap)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(jsonData))

    //Using time
    myTimeMap := map[string]interface{}{
        "TimeNow": time.Now(),
    }

    jsonTimeData, err := json.Marshal(myTimeMap)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(jsonTimeData))

    // Using Struct with no Json tags
    type Student struct { //remember the struct to be decoded or encoded should be exported
        Name   string
        Class  int
        Over18 bool
        Marks  []int
    }

    S1 := &Student{
        Name:   "John",
        Class:  9,
        Over18: false,
        Marks:  []int{22, 34, 42, 40},
    }

    jsonStructData, err := json.Marshal(S1)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(jsonStructData))

    //using structs with explicit json tags
    type NewStudent struct { //remember the struct to be decoded or encoded should be exported
        Name   string `json:"name"`
        Class  int    `json:"class"`
        Over18 bool   `json:"over18"`
        Marks  []int  `json:"marks"`
    }
    S2 := &NewStudent{
        Name:   "John",
        Class:  9,
        Over18: false,
        Marks:  []int{22, 34, 42, 40},
    }

    jsonStructWTData, err := json.Marshal(S2)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(jsonStructWTData))

    // using omit empty for omitting empty fields

    type NewStudent1 struct { //remember the struct to be decoded or encoded should be exported
        Name   string `json:"name"`
        Class  int    `json:"class"`
        Over18 bool   `json:"over18"`
        Marks  []int  `json:"marks,omitempty"`
    }
    S3 := &NewStudent1{
        Name:   "John",
        Class:  9,
        Over18: false,
        Marks:  nil,
    }

    jsonStructWTData, err = json.Marshal(S3)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(jsonStructWTData))

    // Parsing JSON data into map
    jsondata := 
                    `{
                        "name":"John",
                        "class": 9,
                        "over18": false,
                        "marks":[22,34,54,65]
                    }`

    var anotherMap map[string] interface{}

    err = json.Unmarshal([]byte(jsondata), &anotherMap)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(anotherMap)

    // Parsing json into struct
    var myStruct NewStudent

    err = json.Unmarshal([]byte(jsondata), &myStruct)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(myStruct)

    // encoding struct data to json and writing it to stdout
    enc := json.NewEncoder(os.Stdout)
    enc.Encode(S2)

    // decoding json data from a file "ex.json" to a struct
    file, _ := os.Open("ex.json") 
    defer file.Close()

    dec := json.NewDecoder(file)
    dec.Decode(&myStruct)
    fmt.Println(myStruct)
}

Output :

{"Class":9,"name":"John","over 18":false,"subjects":{"marks":[23,23,44,43]}}
{"TimeNow":"2025-08-02T20:15:10.8961321+05:30"}
{"Name":"John","Class":9,"Over18":false,"Marks":[22,34,42,40]}
{"name":"John","class":9,"over18":false,"marks":[22,34,42,40]}
{"name":"John","class":9,"over18":false}
map[class:9 marks:[22 34 54 65] name:John over18:false]
{John 9 false [22 34 54 65]}
{"name":"John","class":9,"over18":false,"marks":[22,34,42,40]}
{John 9 true [22 34 54 65]}

There is much more to explore in encoding/json , I will try to update this blog, as I discover and learn new things.

0
Subscribe to my newsletter

Read articles from Priyansh Sao directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Priyansh Sao
Priyansh Sao