Help us understand the problem. What is going on with this article?

Go言語でJSONを扱う

More than 1 year has passed since last update.

Go言語でJSONを扱う

Go言語でJSONを扱うことがあったので知見をまとめていきます.

JSON形式のレスポンスを取得する

ツイッターなどのAPIにリクエストを送って情報を取得する時,JSON形式で返却されることが多いと思います.
Go言語では受け取るJSONの形式と同じ構造の構造体を定義して,その構造体にはめ込む形でJSONを取得します.

シンプルなJSON形式を取得

まずは,オーソドックスなJSONを取得します.例えば,以下のような形式のJSONが返ってきたとします

{
  "name": "tokumaru",
  "age": 20,
  "job": "student"
}

そのためにGo言語では以下のような構造体を定義します.

type User struct{
  Name string `json:"name"`
  Age int `json:"age"`
  Job string `json: job`
}

文字列を構造体に格納する

userStrという名前の文字列型として先ほどのJSONを受け取った場合は以下のように構造体に格納します.

var user User
err := json.Unmarshal([]byte(jsonStr), &user)

json.Unmarshal()はJSON形式のbyte型の配列を受け取って構造体にバインド的なことをする関数なのでbyte型の配列にキャストしています.

*注意点

構造体の後ろの

.. `json: "name"`
.. `json: "age"`
.. `json: "job"`

は受け取るJSONのキーと同じ名前にしないといけません.また,構造体の要素の名前の頭文字は大文字にするというルールもあります.小文字にしてUser.nameみたいな感じでアクセスしようとすると値が取得できません.

配列形式のJSONを取得

次に,先ほどのJSONを配列形式にした以下のようなJSONがあったとします.

[
  {
    "name": "tokutoku",
    "age": 21,
    "job": "web"
    },
    {
    "name": "toku",
    "age": 20,
    "job": "student"
    },      
    {
    "name": "hoge",
    "age": 22,
    "job": "firefighter"
  }
]

この場合は,User型の配列なので以下のように格納します.

var friends []*User
err = json.Unmarshal([]byte(fiendsStr), &friends)

JSONを構造体の一部に格納する

次に,今までの応用として以下のような構造の構造体があったとします.

type User struct {
    Name string `json:"name"`
    Age int `json:"age"`
    Job string `json:"job"`
    Friends []*User `json:"friends"`
}

この,Friendsの部分に先ほどの配列形式のJSONを保存したいと思います.その場合は,このように格納できます.

var user = &User{}
err := json.Unmarshal([]byte(fiendsStr), &user.Friends)

以下のようにも書けます.

var user *User
user = &User{}
err := json.Unmarshal([]byte(fiendsStr), &user.Friends)

ポイントは,ポインタに空の構造体のポインタを代入しているとこです.

var user *User
err := json.Unmarshal([]byte(fiendsStr), &user.Friends)

これだとエラーが出ます.ヌルポインタにアクセスしようとしたから?みたいな感じです.初級者が気を抜くとやりがちです.自分のことです

ここまでで...

受け取るJSONの形式がわからない場合は?

って疑問が浮かぶと思います.その場合に便利なものがあります.interfaceです.なんでも受け取ります.以下のように使います.

var friends interface{}
err := json.Unmarshal([]byte(fiendsStr), &friends)

構造体にレスポンスが格納できなくてなんで?って時にこれ使ったらいいかもです.

いちいちAPI叩いてテストするのって

めんどいです.

いちいち

アクセストークン取得して,JSON取得して,受け取れてなくて,コード直して,実行して,アクセストークン..

..めんどい

てかそもそもさっきのヌルポインタにアクセスしようとしてたり,API以前の問題だったとか,いちいちリクエストしてテストしてたらしんどいので,自分でレスポンス形式のJSONを文字列で定義してテストしたいこともあるかもしれません.その場合は,このような方法があります.

func main() {
  userStr :=
 `{
    "name": "tokumaru",
    "age": 20,
    "job": "student"
  }`
  var user User // 記事の最初に定義した構造体
  err := json.Unmarshal([]byte(userStr), &user)
}

JSON形式の文字列をベタ書きして格納する方法です.ポイントはバッククオーテーション(`)で囲んでいる点です.これにより改行しても大丈夫になってます.

また,キーはダブルクオーテーション""で囲んで,後ろにカンマをつけます.どう階層の要素の最後にはカンマはつけません.つけてたら怒られます.

まとめ

ざっくりとGo言語でのJSONの扱い方を紹介しました.本当は効率のいいメモリの使い方とか,実行がめっちゃ早いコードを極めるとかしたいですが,基礎の文法を覚える段階で疲弊してしまっています..今回の記事でとりあげたような,普段よく使うけど気を抜くとハマるみたいなことを完璧にしてコーディングのスピードをあげたいと考えています.

gittokkunn
趣味でWebアプリ開発をしています
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away