Menu
Coddy logo textTech

encoding/json with Structs

Part of the Object Oriented Programming section of Coddy's GO journey — lesson 76 of 107.

The encoding/json package lets you convert Go structs to JSON and back. This is essential for APIs, configuration files, and data storage. Struct tags control how fields map to JSON keys.

To convert a struct to JSON, use json.Marshal:

type User struct {
    Name  string `json:"name"`
    Email string `json:"email"`
    Age   int    `json:"age"`
}

func main() {
    user := User{Name: "Alice", Email: "alice@example.com", Age: 30}
    data, _ := json.Marshal(user)
    fmt.Println(string(data))
    // {"name":"Alice","email":"alice@example.com","age":30}
}

The struct tags like `json:"name"` specify the JSON key names. Without tags, Go uses the field name directly. Only exported fields (capitalized) are included in the JSON output.

To convert JSON back to a struct, use json.Unmarshal:

jsonStr := `{"name":"Bob","email":"bob@example.com","age":25}`
var user User
json.Unmarshal([]byte(jsonStr), &user)
fmt.Println(user.Name)  // Bob

Common tag options include omitempty to skip zero values and - to ignore a field entirely:

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

With omitempty, if Price is zero, it won't appear in the JSON. The Internal field is never included regardless of its value.

challenge icon

Challenge

Easy

Let's build a movie catalog system that converts between Go structs and JSON! You'll practice marshaling structs to JSON and unmarshaling JSON back to structs, using struct tags to control the JSON field names.

You'll organize your code across two files:

  • movie.go: Define your movie data model with proper JSON tags.

    Create a Movie struct with the following fields and JSON mappings:

    • Title (string) maps to "title"
    • Director (string) maps to "director"
    • Year (int) maps to "year"
    • Rating (float64) maps to "rating" with omitempty so unrated movies don't show a rating field
    • InternalID (string) should be excluded from JSON entirely using "-"

    Create a function ToJSON(m Movie) string that converts a Movie to a JSON string. Also create FromJSON(jsonStr string) Movie that parses a JSON string back into a Movie struct.

  • main.go: Demonstrate JSON conversion in both directions.

    Read an operation type (encode or decode).

    For encode: Read movie details (title, director, year, rating) on separate lines. Create a Movie with an InternalID of "internal-123", convert it to JSON, and print the result.

    For decode: Read a JSON string, convert it to a Movie struct, and print the movie details in this format:

    Title: [title]
    Director: [director]
    Year: [year]
    Rating: [rating]

    Display the rating with one decimal place. If the rating is 0 (not present in JSON), print Rating: N/A instead.

The following inputs will be provided:

  • Line 1: Operation type (encode or decode)
  • For encode: title, director, year, rating (four lines)
  • For decode: a JSON string (one line)

For example, given:

encode
Inception
Christopher Nolan
2010
8.8

Your output should be:

{"title":"Inception","director":"Christopher Nolan","year":2010,"rating":8.8}

Notice that InternalID doesn't appear in the output because of the "-" tag.

And given:

encode
The Matrix
Wachowskis
1999
0

Your output should be:

{"title":"The Matrix","director":"Wachowskis","year":1999}

Notice that rating is omitted because it's zero and has omitempty.

And given:

decode
{"title":"Interstellar","director":"Christopher Nolan","year":2014,"rating":8.6}

Your output should be:

Title: Interstellar
Director: Christopher Nolan
Year: 2014
Rating: 8.6

And given:

decode
{"title":"Tenet","director":"Christopher Nolan","year":2020}

Your output should be:

Title: Tenet
Director: Christopher Nolan
Year: 2020
Rating: N/A

Cheat sheet

The encoding/json package converts Go structs to JSON and vice versa using json.Marshal and json.Unmarshal.

To convert a struct to JSON:

type User struct {
    Name  string `json:"name"`
    Email string `json:"email"`
    Age   int    `json:"age"`
}

user := User{Name: "Alice", Email: "alice@example.com", Age: 30}
data, _ := json.Marshal(user)
fmt.Println(string(data))
// {"name":"Alice","email":"alice@example.com","age":30}

To convert JSON back to a struct:

jsonStr := `{"name":"Bob","email":"bob@example.com","age":25}`
var user User
json.Unmarshal([]byte(jsonStr), &user)
fmt.Println(user.Name)  // Bob

Struct tags control JSON field mapping:

  • `json:"name"` - maps field to JSON key "name"
  • `json:"price,omitempty"` - omits field if zero value
  • `json:"-"` - excludes field from JSON entirely
type Product struct {
    ID       int     `json:"id"`
    Name     string  `json:"name"`
    Price    float64 `json:"price,omitempty"`
    Internal string  `json:"-"`
}

Only exported fields (capitalized) are included in JSON output.

Try it yourself

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Read operation type
	operation, _ := reader.ReadString('\n')
	operation = strings.TrimSpace(operation)

	if operation == "encode" {
		// Read movie details
		title, _ := reader.ReadString('\n')
		title = strings.TrimSpace(title)

		director, _ := reader.ReadString('\n')
		director = strings.TrimSpace(director)

		yearStr, _ := reader.ReadString('\n')
		yearStr = strings.TrimSpace(yearStr)
		year, _ := strconv.Atoi(yearStr)

		ratingStr, _ := reader.ReadString('\n')
		ratingStr = strings.TrimSpace(ratingStr)
		rating, _ := strconv.ParseFloat(ratingStr, 64)

		// TODO: Create a Movie struct with the read values
		// Set InternalID to "internal-123"
		// Convert to JSON using ToJSON and print the result

	} else if operation == "decode" {
		// Read JSON string
		jsonStr, _ := reader.ReadString('\n')
		jsonStr = strings.TrimSpace(jsonStr)

		// TODO: Convert JSON to Movie using FromJSON
		// Print the movie details in the required format
		// Use fmt.Sprintf("%.1f", rating) for rating formatting
		// If rating is 0, print "Rating: N/A" instead

	}
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming