ぺい

渋谷系アドテクエンジニアの落書き

GoでAPIから取得したJSONを5分でパースする

微妙に面倒なアレ

GoはAPIの用途で、私は結構使うのですが、そのAPIを構築する上で、外部のAPIを使ってデータを集めたりすることもよくあります。そして避けて通れないのが、JSON解析です。自力でやると地味に面倒です。
今回はその作業は5分で終わらせる方法を紹介します。

はよソース

github.com

便利なツール達

Let’s try!!!

目的のJSONを取得する

connpass.com 今回はConnpassのAPIから返ってくるJSONを解析します。

{
    "results_returned": 1,
    "events": [
        {
            "event_url": "https://kikaigakushuu.connpass.com/event/56040/",
            "event_type": "participation",
            "owner_nickname": "keiichirou_miyamoto",
            "series": {
                "url": "https://kikaigakushuu.connpass.com/",
                "id": 2589,
                "title": "人工知能勉強会"
            },
            "updated_at": "2017-04-26T02:47:01+09:00",
            "lat": "35.696575200000",
            "started_at": "2017-05-09T20:00:00+09:00",
            "hash_tag": "geek",
            "title": "強くなるロボティック・ゲームプレイヤーの作り方勉強会「4章 強化学習 前半」",
            "event_id": 56040,
            "lon": "139.771830100000",
            "waiting": 0,
            "limit": 30,
            "owner_id": 10866,
            "owner_display_name": "keiichirou_miyamoto",
            "description": "説明",
            "address": "東京都千代田区神田須田町2丁目19−23  (野村第3ビル4階)",
            "catch": "#人工知能,#機械学習,#深層学習,#ニューラルネット,#ディープラーニング,#初心者",
            "accepted": 17,
            "ended_at": "2017-05-09T22:00:00+09:00",
            "place": "コワーキングスペース秋葉原 Weeyble(ウィーブル)"
        }
    ],
    "results_start": 1,
    "results_available": 1744
}

https://connpass.com/api/v1/event/?keyword=python&count=1
リクエストをブラウザで実行します。

JSON Pretty Linter - JSONの整形と構文チェック コピーして、JSON整形します。 整形したJSONをコピーして、goのソースに貼り付けます。

jsonStrという変数に以下のような感じで代入してください。

var jsonStr = `{
    "results_returned": 1,
    "events": [
        {
            "event_url": "https://kikaigakushuu.connpass.com/event/56040/",
            "event_type": "participation",
            "owner_nickname": "keiichirou_miyamoto",
            "series": {
                "url": "https://kikaigakushuu.connpass.com/",
                "id": 2589,
                "title": "人工知能勉強会"
            },
            "updated_at": "2017-04-26T02:47:01+09:00",
            "lat": "35.696575200000",
            "started_at": "2017-05-09T20:00:00+09:00",
            "hash_tag": "geek",
            "title": "強くなるロボティック・ゲームプレイヤーの作り方勉強会「4章 強化学習 前半」",
            "event_id": 56040,
            "lon": "139.771830100000",
            "waiting": 0,
            "limit": 30,
            "owner_id": 10866,
            "owner_display_name": "keiichirou_miyamoto",
            "description": "説明",
            "address": "東京都千代田区神田須田町2丁目19−23  (野村第3ビル4階)",
            "catch": "#人工知能,#機械学習,#深層学習,#ニューラルネット,#ディープラーニング,#初心者",
            "accepted": 17,
            "ended_at": "2017-05-09T22:00:00+09:00",
            "place": "コワーキングスペース秋葉原 Weeyble(ウィーブル)"
        }
    ],
    "results_start": 1,
    "results_available": 1744
}`

JSONからstructを作成する

https://mholt.github.io/json-to-go/JSON-to-Go: Convert JSON to Go instantly
jsonを食わせて、strcutを生成する。

f:id:tikasan0804:20170426103310p:plain 右に出てるstrcutをコピーしてgoのソースに貼り付ける

type AutoGenerated struct {
    ResultsReturned int `json:"results_returned"`
    Events          []struct {
        EventURL      string `json:"event_url"`
        EventType     string `json:"event_type"`
        OwnerNickname string `json:"owner_nickname"`
        Series        struct {
            URL   string `json:"url"`
            ID    int    `json:"id"`
            Title string `json:"title"`
        } `json:"series"`
        UpdatedAt        time.Time `json:"updated_at"`
        Lat              string    `json:"lat"`
        StartedAt        time.Time `json:"started_at"`
        HashTag          string    `json:"hash_tag"`
        Title            string    `json:"title"`
        EventID          int       `json:"event_id"`
        Lon              string    `json:"lon"`
        Waiting          int       `json:"waiting"`
        Limit            int       `json:"limit"`
        OwnerID          int       `json:"owner_id"`
        OwnerDisplayName string    `json:"owner_display_name"`
        Description      string    `json:"description"`
        Address          string    `json:"address"`
        Catch            string    `json:"catch"`
        Accepted         int       `json:"accepted"`
        EndedAt          time.Time `json:"ended_at"`
        Place            string    `json:"place"`
    } `json:"events"`
    ResultsStart     int `json:"results_start"`
    ResultsAvailable int `json:"results_available"`
}

UmarshalでJSONをパースする

jsonパッケージのUnmarshalでパースして終了。

jsonBytes := ([]byte)(jsonStr)
data := new(AutoGenerated)

if err := json.Unmarshal(jsonBytes, data); err != nil {
    fmt.Println("JSON Unmarshal error:", err)
    return
}
fmt.Println(data.Events[0])

$ go run main.go

以上で、完了です!!!簡単すぎる!!!!

全ソース

package main

import (
    "encoding/json"
    "fmt"
    "time"
)

type AutoGenerated struct {
    ResultsReturned int `json:"results_returned"`
    Events          []struct {
        EventURL      string `json:"event_url"`
        EventType     string `json:"event_type"`
        OwnerNickname string `json:"owner_nickname"`
        Series        struct {
            URL   string `json:"url"`
            ID    int    `json:"id"`
            Title string `json:"title"`
        } `json:"series"`
        UpdatedAt        time.Time `json:"updated_at"`
        Lat              string    `json:"lat"`
        StartedAt        time.Time `json:"started_at"`
        HashTag          string    `json:"hash_tag"`
        Title            string    `json:"title"`
        EventID          int       `json:"event_id"`
        Lon              string    `json:"lon"`
        Waiting          int       `json:"waiting"`
        Limit            int       `json:"limit"`
        OwnerID          int       `json:"owner_id"`
        OwnerDisplayName string    `json:"owner_display_name"`
        Description      string    `json:"description"`
        Address          string    `json:"address"`
        Catch            string    `json:"catch"`
        Accepted         int       `json:"accepted"`
        EndedAt          time.Time `json:"ended_at"`
        Place            string    `json:"place"`
    } `json:"events"`
    ResultsStart     int `json:"results_start"`
    ResultsAvailable int `json:"results_available"`
}

func main() {
    var jsonStr = `{
    "results_returned": 1,
    "events": [
        {
            "event_url": "https://kikaigakushuu.connpass.com/event/56040/",
            "event_type": "participation",
            "owner_nickname": "keiichirou_miyamoto",
            "series": {
                "url": "https://kikaigakushuu.connpass.com/",
                "id": 2589,
                "title": "人工知能勉強会"
            },
            "updated_at": "2017-04-26T02:47:01+09:00",
            "lat": "35.696575200000",
            "started_at": "2017-05-09T20:00:00+09:00",
            "hash_tag": "geek",
            "title": "強くなるロボティック・ゲームプレイヤーの作り方勉強会「4章 強化学習 前半」",
            "event_id": 56040,
            "lon": "139.771830100000",
            "waiting": 0,
            "limit": 30,
            "owner_id": 10866,
            "owner_display_name": "keiichirou_miyamoto",
            "description": "説明",
            "address": "東京都千代田区神田須田町2丁目19−23  (野村第3ビル4階)",
            "catch": "#人工知能,#機械学習,#深層学習,#ニューラルネット,#ディープラーニング,#初心者",
            "accepted": 17,
            "ended_at": "2017-05-09T22:00:00+09:00",
            "place": "コワーキングスペース秋葉原 Weeyble(ウィーブル)"
        }
    ],
    "results_start": 1,
    "results_available": 1744
}`

    jsonBytes := ([]byte)(jsonStr)
    data := new(AutoGenerated)

    if err := json.Unmarshal(jsonBytes, data); err != nil {
        fmt.Println("JSON Unmarshal error:", err)
        return
    }
    fmt.Println(data.Events[0])
}

実際にAPIにリクエストする

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "time"
)

type AutoGenerated struct {
    ResultsReturned int `json:"results_returned"`
    Events          []struct {
        EventURL      string `json:"event_url"`
        EventType     string `json:"event_type"`
        OwnerNickname string `json:"owner_nickname"`
        Series        struct {
            URL   string `json:"url"`
            ID    int    `json:"id"`
            Title string `json:"title"`
        } `json:"series"`
        UpdatedAt        time.Time `json:"updated_at"`
        Lat              string    `json:"lat"`
        StartedAt        time.Time `json:"started_at"`
        HashTag          string    `json:"hash_tag"`
        Title            string    `json:"title"`
        EventID          int       `json:"event_id"`
        Lon              string    `json:"lon"`
        Waiting          int       `json:"waiting"`
        Limit            int       `json:"limit"`
        OwnerID          int       `json:"owner_id"`
        OwnerDisplayName string    `json:"owner_display_name"`
        Description      string    `json:"description"`
        Address          string    `json:"address"`
        Catch            string    `json:"catch"`
        Accepted         int       `json:"accepted"`
        EndedAt          time.Time `json:"ended_at"`
        Place            string    `json:"place"`
    } `json:"events"`
    ResultsStart     int `json:"results_start"`
    ResultsAvailable int `json:"results_available"`
}

func main() {
    url := "https://connpass.com/api/v1/event/?keyword=python&count=1"
    resp, _ := http.Get(url)
    defer resp.Body.Close()
    byteArray, _ := ioutil.ReadAll(resp.Body)

    jsonBytes := ([]byte)(byteArray)
    data := new(AutoGenerated)

    if err := json.Unmarshal(jsonBytes, data); err != nil {
        fmt.Println("JSON Unmarshal error:", err)
        return
    }
    fmt.Println(data.Events[0])
}

以上で終了です。Go最高っすね。