🚢

【Go言語】もう迷わない!JSONの「エンコード・デコード(Marshal・Unmarshal)」の違いと覚え方

に公開

はじめに

Go言語でAPI開発などをしていると必ず遭遇するのが、JSONの変換処理です。

Marshalってどっちだっけ?」「デコードはどっち向き?」と、毎回調べてしまう方も多いのではないでしょうか。

今回は、この「どっちがどっち問題」を視覚的に整理して解説します。


結論:方向で見れば一発!

一番大切なのは、「Goの世界」を基準に、データがどこへ向かっているかを考えることです。

操作 関数 方向
エンコード(Marshal) json.Marshal() Goの構造体 → JSONデータ
デコード(Unmarshal) json.Unmarshal() JSONデータ → Goの構造体
  • エンコード:Goで扱っているデータを、外部へ「出荷(パッキング)」するイメージ
  • デコード:外部から届いたデータ(パズル)を、Goの枠組みに「はめ込む」イメージ

覚え方のコツ:単語のイメージ

英語の意味で紐付けると、より記憶に定着しやすくなります。

用語 英語のイメージ Goでの動き
Marshal (軍隊などを)整列させる バラバラのデータを1行のJSONに整列させる
Unmarshal 整列を解く 1行のデータをバラして、構造体の各項目に配置し直す

ヒント:「Marshal=整列=外に出せる綺麗な形にする」と覚えるとスムーズです!


コードで比較

実際にどのように使い分けるか、コードの形を見比べてみましょう。

エンコードの場合

「Goのデータ」を引数に渡すと、「JSON」が返ってきます。

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

user := User{Name: "Alice", Age: 30}

// 構造体 → JSON(バイト列)
jsonData, err := json.Marshal(user)
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(jsonData)) // {"name":"Alice","age":30}

デコードの場合

「JSON」と「空の入れ物(ポインタ)」を渡して、中身を満たしてもらいます。

jsonData := []byte(`{"name":"Alice","age":30}`)

var u User
// JSON → 構造体(&u に中身が入る)
err := json.Unmarshal(jsonData, &u)
if err != nil {
    log.Fatal(err)
}
fmt.Println(u.Name) // Alice
fmt.Println(u.Age)  // 30

ポイント:なぜ Unmarshal にはポインタを渡すのか?

json.Unmarshal の第2引数には &u のようにポインタを渡す必要があります。これは、関数の内部でデコードした値を変数に書き込むためです。ポインタを渡さないと、関数の外に変更が反映されません。


まとめ

エンコード デコード
関数 json.Marshal() json.Unmarshal()
データの流れ Goの構造体 → JSON JSON → Goの構造体
イメージ 荷物を箱に詰めて出荷 届いた箱を開けて中身を取り出す
第2引数 なし(戻り値でJSONを受け取る) ポインタ(&u)を渡す
  • Goから外へ出すなら Encode(Marshal)
  • 外からGoへ取り込むなら Decode(Unmarshal)

これで次からは迷わずに実装できるはずです。

Discussion