LoginSignup
2
2

More than 5 years have passed since last update.

Goで、DBレコードから良い感じにJSON生成する

Last updated at Posted at 2019-02-28

こんな感じのレスポンスを期待されている時に、JSONをどう生成したかという話。

$ echo '{"books": [{"id":"1","title":"Story about Ruby","amount":20,"created_at":1551354984},{"id":"2","title":"Story about Pearl","amount": -30,"created_at":1551354984}]}' | jq .
{
  "books": [
    {
      "id": "1",
      "title": "Story about Ruby",
      "amount": 20,
      "created_at": 1551354984
    },
    {
      "id": "2",
      "title": "Story about Pearl",
      "amount": -30,
      "created_at": 1551354984
    }
  ]
}

なんか変なデータ構造だけど、実際のプロジェクトコードの構造体名を変えてたりなので、まぁ気にせず😀

// 複数テーブルからのデータを統合した情報
type BookWithAmount struct {
    Book  *models.Book
    Amount int64
}

// 蔵書一覧レスポンス
type booksResponse struct {
    Books []bookRecord `json:"books"`
}

// 蔵書一覧レスポンスに含まれるレコード
type bookRecord struct {
    ID          string `json:"id"`
    Title       string `json:"title"`
    Amount      int64  `json:"amount"`
    CreatedAt   int64  `json:"created_at"`
}

// レスポンス用に蔵書レコードを整形して返す
func getBooksResponse(books []BookWithAmount) booksResponse {
    records := []bookRecord{}
    for _, b := range books {
        r := bookRecord{}
        r.ID = strconv.FormatInt(b.Book.ID, 10)// 文字列希望
        r.Title = b.Book.Title
        r.Amount = map[bool]int64{true: b.Amount, false: -b.Amount}[b.Book.Type == Order]// 場合によってマイナス値に
        r.CreatedAt = b.Book.CreatedAt.Unix()// タイムスタンプ希望
        records = append(records, r)
    }
    return booksResponse{Books: records}
}

func main() {
    // ごにょごにょ...(DBからレコード取得)

    // レスポンス整形
    booksResponse := getBooksResponse(books)
    json, err := json.Marshal(booksResponse)
    if err != nil {
        return
    }

    // ゴニョゴニョ...(レスポンスとして返す)
}

複数テーブルから必要な情報を抜き出して、クライアントが期待する形式にできました👨‍💻🥤

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2