Menu
Coddy logo textTech

JSON永続化レイヤー

CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 102/107。

challenge icon

チャレンジ

簡単

図書館管理システムにデータの永続性を追加しましょう!ライブラリのデータを保存用にJSON形式に変換し、JSON文字列から読み戻すことができるJSON永続化レイヤーを実装します。これは、セッション間でデータを保持する必要がある実際のアプリケーションにとって不可欠です。

コードを5つのファイルに分けて構成します:

  • book.go: シリアル化を制御するためのJSON構造体タグを持つ Book 構造体。各フィールドには、対応するJSONタグ id, title, author, isbn, available を持たせる必要があります。NewBook コンストラクタを含めてください。
  • user.go: id, name, email, borrowed_books 用のJSON構造体タグを持つ User 構造体。NewUser コンストラクタを含めてください。
  • data.go: JSONシリアル化のための転送オブジェクトとして機能する LibraryData 構造体を作成します。これには、Books(Bookポインタのスライス)と Users(Userポインタのスライス)の2つのフィールドがあり、それぞれ適切なJSONタグ(booksusers)が付いている必要があります。
  • library.go: 本とユーザーのマップを持つ Library 構造体。2つの新しいメソッドを追加します:
    • ToJSON() — 2つのスペースのインデントで json.MarshalIndent を使用して、ライブラリのデータをフォーマットされたJSON文字列に変換します。マップからすべての本とユーザーを LibraryData 構造体に収集し、それをシリアル化する必要があります。
    • FromJSON(jsonStr string) — JSON文字列を受け取り、それを LibraryData 構造体にアンマシュール(復元)し、読み込まれた本とユーザーでライブラリのマップを埋めます。
  • main.go: ライブラリを構築し、それをJSONに変換することで永続化レイヤーを実演します。

    本の数を読み取り、次に各本についてID、タイトル、著者、ISBNを読み取ります。次に、ユーザーの数を読み取り、各ユーザーについてID、名前、メールアドレスを読み取ります。ライブラリにデータを入力した後、ToJSON() を呼び出し、結果のJSON文字列を出力します。

以下の入力が提供されます:

  • 本の数、次に各本のID、タイトル、著者、ISBN(それぞれ個別の行)
  • ユーザーの数、次に各ユーザーのID、名前、メールアドレス(それぞれ個別の行)

例えば、以下が与えられた場合:

2
B001
The Go Programming Language
Alan Donovan
978-0134190440
B002
Clean Code
Robert Martin
978-0132350884
1
U001
Alice Smith
alice@library.com

出力は以下のようになります:

{
  "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": []
    }
  ]
}

また、以下が与えられた場合:

1
B100
Design Patterns
Gang of Four
978-0201633610
0

出力は以下のようになります:

{
  "books": [
    {
      "id": "B100",
      "title": "Design Patterns",
      "author": "Gang of Four",
      "isbn": "978-0201633610",
      "available": true
    }
  ],
  "users": []
}

重要: スライスを構築するためにマップを反復処理するときは、本を B001, B002 などの順序(IDのアルファベット順)で追加し、ユーザーも同様に追加してください。これにより、一貫したJSON出力が保証されます。反復処理の前に、マップのキーに対して sort.Strings を使用できます。

LibraryData 構造体は、マップベースのストレージとJSONの配列ベースのフォーマットの間のギャップを埋めます。この転送オブジェクトパターンは、複雑なデータ構造をシリアル化するときによく使われます!

自分で試してみよう

package main

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

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

	// 新しいライブラリを作成する
	library := NewLibrary()

	// 本の数を読み込む
	numBooksStr, _ := reader.ReadString('\n')
	numBooks, _ := strconv.Atoi(strings.TrimSpace(numBooksStr))

	// TODO: 各本の詳細(ID、タイトル、著者、ISBN)を読み込む
	// そしてそれらをライブラリに追加する
	for i := 0; i < numBooks; i++ {
		// TODO: 本のIDを読み込む
		// TODO: 本のタイトルを読み込む
		// TODO: 本の著者を読み込む
		// TODO: 本のISBNを読み込む
		// TODO: 本を作成してライブラリに追加する
	}

	// ユーザーの数を読み込む
	numUsersStr, _ := reader.ReadString('\n')
	numUsers, _ := strconv.Atoi(strings.TrimSpace(numUsersStr))

	// TODO: 各ユーザーの詳細(ID、名前、email)を読み込む
	// そしてそれらをライブラリに追加する
	for i := 0; i < numUsers; i++ {
		// TODO: ユーザーIDを読み込む
		// TODO: ユーザー名を読み込む
		// TODO: ユーザーのemailを読み込む
		// TODO: ユーザーを作成してライブラリに追加する
	}

	// TODO: ライブラリをJSONに変換して出力する
	fmt.Println(library.ToJSON())
}

オブジェクト指向プログラミングのすべてのレッスン