JSON Persistence Layer
Part of the Object Oriented Programming section of Coddy's GO journey — lesson 102 of 107.
Challenge
EasyLet's add data persistence to our Library Management System! You'll implement a JSON persistence layer that can convert your library's data to JSON format for saving, and load it back from JSON strings. This is essential for any real application that needs to preserve data between sessions.
You'll organize your code across five files:
book.go: YourBookstruct with JSON struct tags to control serialization. Each field should have a corresponding JSON tag:id,title,author,isbn, andavailable. Include yourNewBookconstructor.user.go: YourUserstruct with JSON struct tags forid,name,email, andborrowed_books. Include yourNewUserconstructor.data.go: Create aLibraryDatastruct that acts as a transfer object for JSON serialization. It should have two fields:Books(a slice of Book pointers) andUsers(a slice of User pointers), each with appropriate JSON tags (booksandusers).library.go: YourLibrarystruct with maps for books and users. Add two new methods:ToJSON()— converts the library's data to a formatted JSON string usingjson.MarshalIndentwith two-space indentation. It should collect all books and users from the maps into aLibraryDatastruct, then serialize it.FromJSON(jsonStr string)— takes a JSON string, unmarshals it into aLibraryDatastruct, and populates the library's maps with the loaded books and users.
main.go: Demonstrate the persistence layer by building a library and converting it to JSON.Read the number of books, then for each book read its ID, title, author, and ISBN. Next, read the number of users, and for each user read their ID, name, and email. After populating the library, call
ToJSON()and print the resulting JSON string.
The following inputs will be provided:
- Number of books, then each book's ID, title, author, ISBN (each on separate lines)
- Number of users, then each user's ID, name, email (each on separate lines)
For example, given:
2
B001
The Go Programming Language
Alan Donovan
978-0134190440
B002
Clean Code
Robert Martin
978-0132350884
1
U001
Alice Smith
alice@library.comYour output should be:
{
"books": [
{
"id": "B001",
"title": "The Go Programming Language",
"author": "Alan Donovan",
"isbn": "978-0134190440",
"available": true
},
{
"id": "B002",
"title": "Clean Code",
"author": "Robert Martin",
"isbn": "978-0132350884",
"available": true
}
],
"users": [
{
"id": "U001",
"name": "Alice Smith",
"email": "alice@library.com",
"borrowed_books": []
}
]
}And given:
1
B100
Design Patterns
Gang of Four
978-0201633610
0Your output should be:
{
"books": [
{
"id": "B100",
"title": "Design Patterns",
"author": "Gang of Four",
"isbn": "978-0201633610",
"available": true
}
],
"users": []
}Important: When iterating over maps to build your slices, add books in the order: B001, B002, etc. (sorted by ID alphabetically) and users similarly. This ensures consistent JSON output. You can use sort.Strings on the map keys before iterating.
The LibraryData struct bridges the gap between your map-based storage and JSON's array-based format. This transfer object pattern is common when serializing complex data structures!
Try it yourself
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Create a new library
library := NewLibrary()
// Read number of books
numBooksStr, _ := reader.ReadString('\n')
numBooks, _ := strconv.Atoi(strings.TrimSpace(numBooksStr))
// TODO: Read each book's details (ID, title, author, ISBN)
// and add them to the library
for i := 0; i < numBooks; i++ {
// TODO: Read book ID
// TODO: Read book title
// TODO: Read book author
// TODO: Read book ISBN
// TODO: Create book and add to library
}
// Read number of users
numUsersStr, _ := reader.ReadString('\n')
numUsers, _ := strconv.Atoi(strings.TrimSpace(numUsersStr))
// TODO: Read each user's details (ID, name, email)
// and add them to the library
for i := 0; i < numUsers; i++ {
// TODO: Read user ID
// TODO: Read user name
// TODO: Read user email
// TODO: Create user and add to library
}
// TODO: Convert library to JSON and print it
fmt.Println(library.ToJSON())
}
All lessons in Object Oriented Programming
1Fundamentals of Go OOP
External FilesGo Workspace & ModulesPackages & ImportsExported vs Unexported NamesIntroduction to OOP in GoStructs as ClassesDefining Methods on StructsPointer vs Value ReceiversStruct InitializationConstructor FunctionsRecap - Simple Calculator4Interfaces
Introduction to InterfacesImplicit ImplementationInterface as ContractEmpty Interface (any)Type AssertionType SwitchInterface CompositionStringer & Error InterfacesRecap - Shape Calculator7Encapsulation
Exported vs Unexported FieldsPackage-Level EncapsulationGetter & Setter MethodsInformation Hiding in GoRecap - Student Records10Generics (Go 1.18+)
Introduction to GenericsType ParametersType ConstraintsGeneric StructsGeneric Methods WorkaroundRecap - Generic Collection2Types & Structs Deep Dive
Basic & Composite TypesCustom Type DefinitionsStruct TagsAnonymous StructsNested StructsZero Values & DefaultsRecap - Contact Book5Composition Over Inheritance
Why Go Has No InheritanceStruct Embedding BasicsMethod PromotionEmbedding Multiple StructsEmbedding vs AggregationShadowing Embedded MethodsRecap - Employee Hierarchy8Error Handling & OOP
The error InterfaceCustom Error TypesError Wrapping (fmt.Errorf)Sentinel Errorserrors.Is() and errors.As()Panic, Defer, and RecoverRecap - File Parser3Pointers & Memory
Pointer Basics in GoPointers to StructsPass by Value vs ReferenceThe new() FunctionGarbage Collection in GoRecap - Linked List Builder6Polymorphism in Go
Polymorphism via InterfacesDuck Typing in GoInterface Satisfaction RulesPolymorphic CollectionsDependency InjectionRecap - Payment Processor9Concurrency & OOP
Goroutines BasicsChannels & CommunicationBuffered vs Unbuffered ChanSelect Statementsync.Mutex & sync.RWMutexsync.WaitGroupThread-Safe Struct DesignRecap - Worker Pool12Advanced OOP Concepts
Functional Options PatternBuilder Pattern in GoMethod ChainingType Aliases vs DefinitionsReflection BasicsCode Generation Overview15Project: Library Management
Project Overview & StructureBook and User Structs