Working with JSON in Go

Encoding and decoding JSON data in Go applications

🔄 What is JSON in Go?

JSON (JavaScript Object Notation) is a lightweight data format. Go's encoding/json package provides powerful tools to convert Go structs to JSON and vice versa effortlessly.


// Simple JSON marshaling example
package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    p := Person{Name: "Alice", Age: 30}
    jsonData, _ := json.Marshal(p)
    fmt.Println(string(jsonData))
}
                                    

Output:

{"name":"Alice","age":30}

JSON Operations in Go

📤

Marshal

Convert Go structs to JSON

data, err := json.Marshal(struct)
📥

Unmarshal

Convert JSON to Go structs

err := json.Unmarshal(data, &struct)
🏷️

Struct Tags

Control JSON field names

Name string `json:"name"`
🎯

Custom Types

Handle complex JSON structures

type CustomTime time.Time

🔹 JSON Marshal (Encoding)

Convert Go data structures to JSON format:

package main

import (
    "encoding/json"
    "fmt"
)

type User struct {
    ID       int      `json:"id"`
    Name     string   `json:"name"`
    Email    string   `json:"email"`
    Hobbies  []string `json:"hobbies"`
    Active   bool     `json:"active"`
}

func main() {
    user := User{
        ID:      1,
        Name:    "John Doe",
        Email:   "[email protected]",
        Hobbies: []string{"reading", "coding", "gaming"},
        Active:  true,
    }

    // Marshal to JSON
    jsonData, err := json.Marshal(user)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    fmt.Println("JSON:", string(jsonData))

    // Pretty print JSON
    prettyJSON, _ := json.MarshalIndent(user, "", "  ")
    fmt.Println("Pretty JSON:\n", string(prettyJSON))
}

Output:

JSON: {"id":1,"name":"John Doe","email":"[email protected]","hobbies":["reading","coding","gaming"],"active":true}

Pretty JSON:
{
"id": 1,
"name": "John Doe",
"email": "[email protected]",
"hobbies": ["reading","coding","gaming"],
"active": true
}

🔹 JSON Unmarshal (Decoding)

Convert JSON data back to Go structures:

package main

import (
    "encoding/json"
    "fmt"
)

type Product struct {
    ID    int     `json:"id"`
    Name  string  `json:"name"`
    Price float64 `json:"price"`
}

func main() {
    // JSON string
    jsonStr := `{"id":123,"name":"Laptop","price":999.99}`

    // Unmarshal to struct
    var product Product
    err := json.Unmarshal([]byte(jsonStr), &product)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    fmt.Printf("Product: %+v\n", product)
    fmt.Printf("Name: %s, Price: $%.2f\n", product.Name, product.Price)

    // Unmarshal to map for dynamic JSON
    var data map[string]interface{}
    json.Unmarshal([]byte(jsonStr), &data)
    fmt.Println("Map:", data)
}

Output:

Product: {ID:123 Name:Laptop Price:999.99}
Name: Laptop, Price: $999.99
Map: map[id:123 name:Laptop price:999.99]

🔹 JSON Struct Tags

Control JSON field behavior with struct tags:

package main

import (
    "encoding/json"
    "fmt"
)

type Employee struct {
    ID       int    `json:"employee_id"`
    Name     string `json:"full_name"`
    Password string `json:"-"`                    // Ignore field
    Email    string `json:"email,omitempty"`      // Omit if empty
    Salary   int    `json:"salary,string"`        // Convert to string
}

func main() {
    emp := Employee{
        ID:       101,
        Name:     "Alice Smith",
        Password: "secret123",
        Email:    "",
        Salary:   50000,
    }

    jsonData, _ := json.MarshalIndent(emp, "", "  ")
    fmt.Println("JSON with tags:")
    fmt.Println(string(jsonData))
}

Output:

JSON with tags:
{
"employee_id": 101,
"full_name": "Alice Smith",
"salary": "50000"
}

🔹 Working with JSON Files

Read and write JSON data to files:

package main

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

type Config struct {
    AppName string `json:"app_name"`
    Port    int    `json:"port"`
    Debug   bool   `json:"debug"`
}

func main() {
    // Write JSON to file
    config := Config{
        AppName: "MyApp",
        Port:    8080,
        Debug:   true,
    }

    file, _ := os.Create("config.json")
    defer file.Close()

    encoder := json.NewEncoder(file)
    encoder.SetIndent("", "  ")
    encoder.Encode(config)
    fmt.Println("Config saved to file")

    // Read JSON from file
    var loadedConfig Config
    file, _ = os.Open("config.json")
    defer file.Close()

    decoder := json.NewDecoder(file)
    decoder.Decode(&loadedConfig)
    fmt.Printf("Loaded config: %+v\n", loadedConfig)
}

Output:

Config saved to file
Loaded config: {AppName:MyApp Port:8080 Debug:true}

🧠 Test Your Knowledge

Which function converts Go structs to JSON?