こんな感じのレスポンスを期待されている時に、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
}
// ゴニョゴニョ...(レスポンスとして返す)
}
複数テーブルから必要な情報を抜き出して、クライアントが期待する形式にできました👨💻🥤