GoのJSON操作【プログラミング初心者向け教材】

プログラミング

JSONは外部のAPIや他システムと連携する際のデータフォーマットとしてよく用いられるフォーマットです。

プログラム内では受け取ったJSONデータをシステム内に取り込んだり、その逆を行ったりすることがあるため、JSONデータの操作が必要となります。

本記事では、GoにおけるJSONデータの操作についてまとめます。

プログラミング初心者の方の学習や、忘れてしまった方の復習として、参考にしていただければ幸いです。

記載しているプログラムは、Go1.15.2を使って動作確認をしています。

GoのJSON操作

GoのJSON操作として以下の内容を採り上げます。

  • JSONを扱うパッケージ
  • JSONファイルの読み込み
  • JSONデータの参照
  • JSONデータの追加
  • JSONデータの削除
  • 文字列からJSONオブジェクトへの変換
  • JSONオブジェクトから文字列への変換

JSONを扱うパッケージ

GoでJSONデータを扱うには、標準で提供されている encoding/json パッケージを使います。
以下のように、import が必要となります。

import (
    "encoding/json"
)

なお、GoでJSONデータを扱う際には、構造体のメンバにマッピングさせる方法とさせない方法があります。
今回はマッピングさせずに、自由にデータを追加や削除する方式で進めていきます。

JSONファイルの読み込み

本記事では、以下のJSONデータを扱います。

{
  "string": "文字列",
  "int": 2020,
  "bool": true,
  "null": null,
  "array": [
    {"no": 1, "name": "JavaScript"},
    {"no": 2, "name": "Python"}
  ],
  "object": {
    "no": 3,
    "name": "Java"
  }
}

この内容を data.json というファイルで保存し、プログラムから読み込みます。

ファイルから読み込んだ文字列を、json.Unmarshal を使ってJSONオブジェクトに変換します。
GoではmapとarrayでJSONオブジェクトを扱います。

s, _ := ioutil.ReadFile("./data.json")
var jsondata map[string]interface{}
json.Unmarshal([]byte(s), &jsondata)
fmt.Println(jsondata) // -> map[array:[map[name:JavaScript・・・(省略)

上記のプログラムでは、ファイルから読み込んだJSON文字列のsを json.Unmarshal でjsondataというmapに変換しています。
変換したマップを表示させるとjson文字列がmapやarrayに変換されていることがわかります。

JSONデータの参照

JSONオブジェクトのデータを参照するには、mapとarrayの参照の仕方と同じになります。

文字列や整数の参照は、直接キー名を指定して値を取得します。

fmt.Println(jsondata["string"]) // -> 文字列
fmt.Println(jsondata["int"]) // -> 2020
fmt.Println(jsondata["bool"]) // -> true
fmt.Println(jsondata["null"]) // -> <nil>

arrayの参照は、一旦スライスとしてキャストした後にインデックスを指定して参照します。

a := jsondata["array"].([]interface{})
fmt.Println((a[0].(map[string]interface{}))["no"]) // -> 1
fmt.Println((a[0].(map[string]interface{}))["name"]) // -> JavaScript
fmt.Println((a[1].(map[string]interface{}))["no"]) // -> 2
fmt.Println((a[1].(map[string]interface{}))["name"]) // -> Python

スライスなので、ループによる参照も可能です。

for _, value := range a {
    fmt.Println(value.(map[string]interface{})["no"]) // -> 1 -> 2
    fmt.Println(value.(map[string]interface{})["name"]) // -> JavaScript -> Python
}

オブジェクトの参照は、一旦mapにキャストした後に、ネストするオブジェクトのキー名を参照して値を取得することができます。

fmt.Println(jsondata["object"].(map[string]interface{})["no"]) // -> 3
fmt.Println(jsondata["object"].(map[string]interface{})["name"]) // -> Java

JSONデータの追加

JSONオブジェクトにデータを追加するには、mapやarrayへの追加の仕方と同じになります。

文字列や整数値の追加は、jsonオブジェクトに直接キーと値を指定します。

jsondata["string2"] = "文字列2"
jsondata["int2"] = 2021
jsondata["bool2"] = false
jsondata["null2"] = nil

arrayに追加するには、直接追加が出来ないため現在のarrayと追加したい情報を append した新しいarrayで更新します。

jsondata["array"] = append(
    jsondata["array"].([]interface{}),
    map[string]interface{}{"no": 4, "name": "Ruby"})

オブジェクトを追加するには、オブジェクトをネストさせてキーと値を指定します。

jsondata["object"].(map[string]interface{})["object2"] =
    map[string]interface{}{"no": 5, "name": "Go"}

上記で追加したJSONオブジェクト全体を表示させると以下のようになります。

{
  "array": [
    {
      "name": "JavaScript",
      "no": 1
    },
    {
      "name": "Python",
      "no": 2
    },
    {
      "name": "Ruby",
      "no": 4
    }
  ],
  "bool": true,
  "bool2": false,
  "int": 2020,
  "int2": 2021,
  "null": null,
  "null2": null,
  "object": {
    "name": "Java",
    "no": 3,
    "object2": {
      "name": "Go",
      "no": 5
    }
  },
  "string": "文字列",
  "string2": "文字列2"
}

JSONデータの削除

JSONオブジェクトからデータを削除するには、mapやarrayの削除方法と同じになります。
arrayは直接削除が出来ないため、削除したい要素を取り除いた新しいarrayで更新します。

delete(jsondata, "string2")
delete(jsondata, "int2")
delete(jsondata, "bool2")
delete(jsondata, "null2")
jsondata["array"] = jsondata["array"].([]interface{})[0:2]
delete(jsondata["object"].(map[string]interface{}), "object2")

上記で削除した結果のJSONオブジェクト全体を表示させると以下のようになります。
(追加した分が削除されて、元の状態に戻っています)

{
  "array": [
    {
      "name": "JavaScript",
      "no": 1
    },
    {
      "name": "Python",
      "no": 2
    }
  ],
  "bool": true,
  "int": 2020,
  "null": null,
  "object": {
    "name": "Java",
    "no": 3
  },
  "string": "文字列"
}

文字列からJSONオブジェクトへの変換

文字列からJSONオブジェクトへ変換するには、json.Unmarshal を使います。

str := "{\"text\": \"テキスト\", \"num\": 1}"
var j map[string]interface{}
json.Unmarshal([]byte(str), &j)
fmt.Println(j) // -> map[num:1 text:テキスト]

JSONオブジェクトから文字列への変換

JSONオブジェクトから文字列へ変換するには、json.Marshal を使います。

s, _ = json.Marshal(j)
fmt.Println(string(s)) // -> {"num":1,"text":"テキスト"}

改行も入れて整形した文字列へ変換するには、json.MarshalIndent を使います。

s, _ = json.MarshalIndent(j, "", "  ")
fmt.Println(string(s))

上記のプログラムを実行すると、以下のように表示されます。

{
  "num": 1,
  "text": "テキスト"
}

JSONデータを自由に扱えるようになろう

最近では、JSON形式のデータをプログラム内だけではなく、ログやインフラ等の設定情報、保存用データなど様々な部分で使われることが増えてきました。

プログラマブルなデータフォーマットとして保存することで、プログラムで自由に解析をしやすくする意図があります。

ちょっとしたJSON解析プログラムを作ることで、今までExcelで集計していた業務を効率化することが出来たり、プログラムによってチェックすることで作業ミスを防止することも出来ます。

こうした日頃の作業をプログラマブルに出来ないか考えてみるのも良いと思います。

 

今回はGoのJSON操作についてまとめました。

以上、参考になれば幸いです。

コメント

タイトルとURLをコピーしました