Go言語の構造体とJSONの相互変換方法!エンコード・デコード例を初心者向けに解説
生徒
「Go言語で構造体とJSONのデータをやり取りしたいんですが、どうやって変換するんですか?」
先生
「Goではencoding/jsonという標準パッケージを使って、構造体とJSONの相互変換が簡単にできますよ。」
生徒
「エンコードとかデコードって難しそうです…」
先生
「大丈夫です。順を追って、やさしく説明していきますね!」
1. Go言語でJSONを使うための基本知識
Go言語では、encoding/jsonパッケージを使うことで、構造体をJSON形式に変換(エンコード)したり、JSONデータを構造体に変換(デコード)することができます。JSON(ジェイソン)は、データを人間にもコンピュータにも読みやすく表現するための形式で、Web APIなどでよく使われます。
2. 構造体をJSONに変換する方法(エンコード)
まず、構造体をJSON形式の文字列に変換する方法を紹介します。これをエンコードといいます。以下はその例です。
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
}
func main() {
user := User{Name: "田中太郎", Email: "taro@example.com", Age: 30}
jsonData, err := json.Marshal(user)
if err != nil {
fmt.Println("エンコードエラー:", err)
return
}
fmt.Println(string(jsonData))
}
json.Marshal関数は、構造体をJSON形式に変換します。タグ(`json:"name"`のような記述)を使うことで、JSONで使いたいキー名を自由に指定できます。
上記のコードを実行すると、次のようなJSONが出力されます。
{"name":"田中太郎","email":"taro@example.com","age":30}
3. JSONを構造体に変換する方法(デコード)
今度は、JSON形式のデータを構造体に変換する方法を紹介します。これをデコードといいます。
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
}
func main() {
jsonStr := `{"name":"山田花子","email":"hanako@example.com","age":25}`
var user User
err := json.Unmarshal([]byte(jsonStr), &user)
if err != nil {
fmt.Println("デコードエラー:", err)
return
}
fmt.Printf("名前: %s\nメール: %s\n年齢: %d\n", user.Name, user.Email, user.Age)
}
json.Unmarshal関数を使うと、JSONの文字列を構造体に読み込むことができます。[]byte型に変換して渡す必要がある点に注意しましょう。
名前: 山田花子
メール: hanako@example.com
年齢: 25
4. JSONのキーと構造体のフィールド名を合わせるコツ
構造体のフィールド名とJSONのキー名が一致しない場合でも、タグを使えば対応可能です。たとえば、JSONでuser_nameというキーを使いたい場合は、次のように書きます。
type User struct {
UserName string `json:"user_name"`
}
このようにすることで、構造体とJSONの間で柔軟なデータのやり取りが可能になります。
5. 小文字のフィールドが無視される理由
Go言語では、小文字で始まるフィールド名は外部パッケージからアクセスできません。そのため、エンコードやデコードを行う際に無視されてしまいます。必ず大文字で始めましょう。
type User struct {
name string `json:"name"` // 小文字ではエンコードされない!
}
このようなケースでは、nameはJSONに含まれません。Goの構造体とJSONを扱うときの重要なポイントです。
まとめ
Go言語の構造体とJSONの相互変換は、Web 開発やAPI連携を行う上で非常に重要な基礎知識です。この記事で紹介したように、Goでは標準パッケージである
encoding/json を利用することで、複雑に見えるエンコード(構造体→JSON)とデコード(JSON→構造体)がとてもシンプルに扱えます。
特に、Goの構造体タグ(`json:"name"` のような記述)は、JSON のキー名と構造体のフィールド名を柔軟に対応させるための重要な仕組みであり、
WebアプリケーションやAPIの設計では欠かせないポイントになります。
また、フィールドが大文字で始まる必要があるというGo特有の仕様は、最初につまずきやすい部分ですが、慣れてしまえば自然と身につくルールです。
これを理解することで、データが正しくエンコードされない原因を素早く判断できるようになり、プログラムの品質向上にもつながります。
JSONはシステム間のデータ交換で最も一般的に利用されている形式であり、Go言語では軽量で効率の良い処理が行えるため、バックエンドの開発や外部サービスとの通信でよく用いられます。
構造体というGoの堅牢な型システムと、柔軟なJSONフォーマットをつなぐ力を持つencoding/jsonパッケージを理解することで、データ処理の幅が大きく広がります。
以下では、記事で学んだ内容をさらに深めるための応用サンプルも紹介し、構造体とJSONの変換をよりスムーズに行える実践コードを掲載します。
実践的な構造体とJSONの応用例
次の例では、構造体のフィールドにオプションタグをつけて、JSON の出力形式を調整したり、デコード時に特定の値をスキップする方法を紹介します。
package main
import (
"encoding/json"
"fmt"
)
type Product struct {
Name string `json:"name"`
Price int `json:"price"`
Discount *int `json:"discount,omitempty"` // 値がnilならJSONに含めない
}
func main() {
discount := 20
p1 := Product{Name: "りんご", Price: 150, Discount: &discount}
p2 := Product{Name: "バナナ", Price: 120, Discount: nil}
json1, _ := json.Marshal(p1)
json2, _ := json.Marshal(p2)
fmt.Println(string(json1))
fmt.Println(string(json2))
// JSON → 構造体のデコード例
jsonStr := `{"name":"みかん","price":200,"discount":15}`
var p3 Product
if err := json.Unmarshal([]byte(jsonStr), &p3); err == nil {
fmt.Printf("商品名:%s 価格:%d 割引:%d\n", p3.Name, p3.Price, *p3.Discount)
}
}
このように、構造体タグを使うことで、出力形式の調整や存在しないフィールドの扱いを柔軟にコントロールできます。 GoのJSON処理は規則が明確で、動作も予測しやすいため、初心者でも慣れれば扱いやすい設計となっています。
生徒
「構造体とJSONの変換ってもっと難しいものだと思っていましたが、思ったよりシンプルなんですね!」
先生
「そうでしょう?GoのJSONパッケージはとても直感的ですし、型の安全性も保ちながらデータのやり取りができます。」
生徒
「タグを使うことでキー名を変えられるのは便利ですね。APIを作る時にも役立ちそうです!」
先生
「まさにその通りです。構造体タグはAPI開発に欠かせません。実務でも頻繁に使いますよ。」
生徒
「あと、小文字のフィールドがJSONに出ない理由もよく分かりました。エラーじゃないから気づきにくいですね。」
先生
「Goの仕様を理解すると原因が分かりやすくなります。構造体とJSONの関係は、Goのデータ処理の基本なので、これからも応用できますよ。」
生徒
「エンコードとデコード、どちらも練習してみます!API からのデータ読み込みにも挑戦したくなりました!」