Go言語で JSON を扱う際には、標準パッケージ encoding/json
を使用するのが一般的です。
このパッケージには、メモリ上で一括変換を行う方法と、ストリームを通じて順次変換する方法の2通りがあります。
まずはじめに、それぞれの違いを簡単にまとめておきましょう。
メモリ処理とストリーム処理の違い(概要)
特徴 | メモリ処理 | ストリーム処理 |
---|---|---|
処理方法 | データを一括で読み書きする | データを少しずつ読み書きする |
使用関数 | json.Marshal / json.Unmarshal |
json.Encoder / json.Decoder |
対象データ | []byte (メモリ上の全データ) |
io.Reader / io.Writer (データの流れ) |
適する場面 | 小〜中規模のデータ、簡単な変換 | 大規模データ、リアルタイム・逐次処理 |
このあと、それぞれの方法を具体的に見ていきます。
エンコードとデコードとは?
GoでJSONを扱う際によく出てくる「エンコード」と「デコード」は、次のような意味です:
用語 | 意味 | 関数例 |
---|---|---|
エンコード | Goの構造体などのデータをJSON形式の文字列に変換する処理 | json.Marshal / Encode |
デコード | JSON形式の文字列をGoの構造体などのデータに戻す処理 | json.Unmarshal / Decode |
たとえば、次のような処理がエンコードとデコードの典型です:
jsonBytes, _ := json.Marshal(myStruct) // ← エンコード(Go → JSON)
json.Unmarshal(jsonBytes, &myStruct) // ← デコード(JSON → Go)
メモリで JSON を処理する
json.Marshal
/ json.Unmarshal
の実装例
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
// 構造体からJSONへ(エンコード)
p := Person{Name: "Alice", Age: 30}
jsonBytes, err := json.Marshal(p)
if err != nil {
panic(err)
}
fmt.Println("JSON出力:", string(jsonBytes))
// JSONから構造体へ(デコード)
var decoded Person
err = json.Unmarshal(jsonBytes, &decoded)
if err != nil {
panic(err)
}
fmt.Printf("構造体に戻した結果: %+v\n", decoded)
}
メモリ処理の特徴
ストリームで JSON を処理する
json.NewDecoder
/ json.NewEncoder
の実装例
package main
import (
"encoding/json"
"fmt"
"os"
)
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price"`
}
func main() {
// ファイルにJSONを書き出す(エンコード)
f, err := os.Create("product.json")
if err != nil {
panic(err)
}
defer f.Close()
encoder := json.NewEncoder(f)
product := Product{ID: 1, Name: "Notebook", Price: 1299.99}
if err := encoder.Encode(product); err != nil {
panic(err)
}
fmt.Println("ファイルにJSONを書き出しました")
// ファイルからJSONを読み込む(デコード)
f2, err := os.Open("product.json")
if err != nil {
panic(err)
}
defer f2.Close()
decoder := json.NewDecoder(f2)
var p Product
if err := decoder.Decode(&p); err != nil {
panic(err)
}
fmt.Printf("読み込んだ構造体: %+v\n", p)
}
ストリーム処理の特徴
io.Reader
/ io.Writer
を活用メモリ処理とストリーム処理の比較
項目 | メモリ処理 (Marshal / Unmarshal ) |
ストリーム処理 (Encoder / Decoder ) |
---|---|---|
対象データ | 一括データ([]byte ) |
順次データ(io.Reader / Writer ) |
適するデータ規模 | 小〜中規模 | 大規模・連続データ |
メリット | 簡単・高速 | 柔軟・低メモリ |
まとめ
json.Marshal
/ json.Unmarshal
は、データを一括で処理するのに適しており、簡潔なコードが書けます。json.Encoder
/ json.Decoder
は、データを少しずつ処理したい場合に便利で、大規模データやリアルタイム処理に向いています。処理するデータの大きさや性質に応じて、最適な方法を選ぶことが、Goでの効率的なJSON処理のポイントです。