ryota21silvaの技術ブログ

Funna(ふんな)の技術ブログ

これまで学んだ技術の備忘録。未来の自分が救われることを信じて

【Go】JSONの入れ子を構造体に変換する

■ はじめに

APIから返ってくるJSON文字列をGolangの構造体に変換したいと思います。

JSONを構造体に変換する基本形

例えば以下JSONを構造体にマッピングしたい場合

{
    "book":{
        "google_books_id": "Wx1dLwEACAAJ",
        "title": "リーダブルコード",
        "authors": ["Dustin Boswell","Trevor Foucher"],
        "description": "読んでわかるコードの重要性と方法について解説",
        "isbn_10": "4873115655",
        "isbn_13": "9784873115658",
        "page_count": 237,
        "published_year": 2012,
        "published_month": 6
    }
}

以下のように記述すればOKです。

type BookRequestParameter struct {
    GoogleBooksId string    `json:"google_books_id"`
    Title         string    `json:"title"`
        Authors   []string      `json:"authors"`
    Description   string    `json:"description"`
    Isbn_10       string    `json:"isbn_10"`
    Isbn_13       string    `json:"isbn_13"`
    PageCount     int       `json:"page_count"`
    PublishedYear   int     `json:"published_year"`
    PublishedMonth   int    `json:"published_month"`
}

JSON入れ子を構造体に変換する

以下のようなJSON入れ子を構造体にマッピングする場合

{
    "book":{
        "google_books_id": "Wx1dLwEACAAJ",
        "title": "リーダブルコード",
        "authors": ["Dustin Boswell","Trevor Foucher"],
        "description": "読んでわかるコードの重要性と方法について解説",
        "isbn_10": "4873115655",
        "isbn_13": "9784873115658",
        "page_count": 237,
        "published_year": 2012,
        "published_month": 6
    },
    "memo": {
        "body": "メモです。"
    }
}

以下のどちらかの方法で構造体をフィールドに持つ構造体を定義してあげれば良いです。

type RegisterUserBookRequestParameter struct {
    Book BookRequestParameter `json:"book"`
    Memo MemoRequestParameter `json:"memo"`
}

type BookRequestParameter struct {
    GoogleBooksId string    `json:"google_books_id"`
    Title         string    `json:"title"`
    Description   string    `json:"description"`
    Isbn_10       string    `json:"isbn_10"`
    Isbn_13       string    `json:"isbn_13"`
    PageCount     int       `json:"page_count"`
    PublishedYear   int  `json:"published_year"`
    PublishedMonth   int     `json:"published_month"`
    PublishedDate   int  `json:"published_date"`
}

type MemoRequestParameter struct {
    Body          string    `json:"body"`
}
type RegisterUserBookRequestParameterr struct {
    Book struct  {
        GoogleBooksId string    `json:"google_books_id"`
        Title         string    `json:"title"`
        Description   string    `json:"description"`
        Isbn_10       string    `json:"isbn_10"`
        Isbn_13       string    `json:"isbn_13"`
        PageCount     int       `json:"page_count"`
        PublishedYear   int  `json:"published_year"`
        PublishedMonth   int     `json:"published_month"`
        PublishedDate   int  `json:"published_date"`
    } `json:"book"`
    Memo struct {
        Body          string    `json:"body"`
    }`json:"user_book"`
}

実際にAPIを叩いて受け取ったレスポンスを構造体に変換してみる

今回はGoogle Books APIを題材にしてみます。 Google Books APIhttps://www.googleapis.com/books/v1/volumes?q=検索したい書籍名の形式でリクエストを投げられます。

以下のコードはGoogle Books APIから受け取ったJSON形式のレスポンスをResponseBodyFromGoogleBooksApi構造体に変換しています。

// ResponseBodyFromGoogleBooksApi : GoogleBooksAPIを叩いた時のJSONレスポンスを格納する構造体
type ResponseBodyFromGoogleBooksApi struct {
    Items []Item `json:"items"`
}

type Item struct {
    ID         string     `json:"id"`
    VolumeInfo VolumeInfo `json:"volumeInfo"`
}

type VolumeInfo struct {
    Title               string               `json:"title"`
    Authors             []string             `json:"authors"`
    PublishedDate       string               `json:"publishedDate"`
    Description         string               `json:"description"`
    IndustryIdentifiers []IndustryIdentifier `json:"industryIdentifiers"`
    PageCount           int                  `json:"pageCount"`
}

type IndustryIdentifier struct {
    Type       string `json:"type"`
    Identifier string `json:"identifier"`
}

type GoogleBooksApiClientInterface interface {
    SendRequest(searchWord string) (ResponseBodyFromGoogleBooksApi, error)
}


func (client googleBooksApiClient) SendRequest(searchWord string) (model.ResponseBodyFromGoogleBooksApi, error) {
  searchURL := "https://www.googleapis.com/books/v1/volumes?q=" + searchWord

  // GoogleBooksAPIを叩く
  res, err := http.Get(searchURL)
  if err != nil {
    // エラーハンドリング
  }

  defer res.Body.Close()

  body, err := ioutil.ReadAll(res.Body)
  if err != nil {
    // エラーハンドリング
  }

  // JSONエンコードされたデータをparseして、構造体の変数responseBodyFromGoogleBooksApiに格納する
  var responseBodyFromGoogleBooksApi model.ResponseBodyFromGoogleBooksApi
  if err := json.Unmarshal(body, &responseBodyFromGoogleBooksApi); err != nil {
    // エラーハンドリング
  }

  return responseBodyFromGoogleBooksApi, nil
}

JSONを構造体に変換する便利ツール

JSONを構造体の形式にマッピングするためには、json-to-goを使うと便利です。

json-to-go