json.Encoder / Decoder
| 対応: | Go 1.0(2012) |
|---|
『json.Encoder』と『json.Decoder』はストリームに対してJSONの読み書きを行います。ファイルやネットワークなどの io.Writer / io.Reader と組み合わせてメモリ効率よく処理できます。
構文
// Encoder を作成して値をJSONとして書き込む enc := json.NewEncoder(writer) err := enc.Encode(値) // Decoder を作成してJSONを読み込んでデコードする dec := json.NewDecoder(reader) err := dec.Decode(&v)
関数一覧
| 関数 / メソッド | 概要 |
|---|---|
| json.NewEncoder(w) | io.Writer をラップした Encoder を作成します。 |
| enc.Encode(v) | v をJSONエンコードして Writer に書き込みます。末尾に改行が自動付加されます。 |
| enc.SetIndent(prefix, indent) | Encode() の出力をインデント付きに設定します。 |
| json.NewDecoder(r) | io.Reader をラップした Decoder を作成します。 |
| dec.Decode(v) | Reader からJSONを読み込んで v にデコードします。 |
| dec.More() | 配列やオブジェクトに次の要素があるか確認します。 |
サンプルコード
sample_json_encoder_decoder.go
package main
import (
"encoding/json"
"fmt"
"os"
"strings"
)
type Fighter struct {
Name string `json:"name"`
Power int `json:"power"`
}
func main() {
// Encoder で標準出力に直接JSONを書き出す
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
fighters := []Fighter{
{Name: "Son Goku", Power: 9000},
{Name: "Vegeta", Power: 8000},
}
fmt.Println("--- Encoder で出力 ---")
enc.Encode(fighters)
// Decoder でJSON文字列をデコードする
jsonData := `
{"name":"Krillin","power":1770}
{"name":"Piccolo","power":3500}
`
dec := json.NewDecoder(strings.NewReader(jsonData))
fmt.Println("--- Decoder で読み込み ---")
for dec.More() {
var f Fighter
if err := dec.Decode(&f); err != nil {
fmt.Println("デコードエラー:", err)
break
}
fmt.Printf("%s: %d\n", f.Name, f.Power)
}
}
go run json_encoder_decoder.go
--- Encoder で出力 ---
[
{
"name": "Son Goku",
"power": 9000
},
{
"name": "Vegeta",
"power": 8000
}
]
--- Decoder で読み込み ---
Krillin: 1770
Piccolo: 3500
json_encoder_decoder2.go — HTTPハンドラーでJSONを返す
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
)
type Fighter struct {
Name string `json:"name"`
Power int `json:"power"`
}
// HTTPハンドラーでJSONを直接レスポンスに書き込みます。
func fightersHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
fighters := []Fighter{
{Name: "Son Goku", Power: 9000},
{Name: "Vegeta", Power: 8000},
{Name: "Piccolo", Power: 3500},
}
if err := enc.Encode(fighters); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func main() {
// httptest.NewRecorder でレスポンスをキャプチャします。
w := httptest.NewRecorder()
r := httptest.NewRequest("GET", "/fighters", nil)
fightersHandler(w, r)
fmt.Println(w.Body.String())
}
go run json_encoder_decoder2.go
[
{
"name": "Son Goku",
"power": 9000
},
{
"name": "Vegeta",
"power": 8000
},
{
"name": "Piccolo",
"power": 3500
}
]
json_encoder_decoder3.go — ファイルへの書き込みとファイルからの読み込み
package main
import (
"encoding/json"
"fmt"
"os"
)
type Fighter struct {
Name string `json:"name"`
Power int `json:"power"`
}
func main() {
// ファイルにJSONを書き込みます。
file, _ := os.Create("fighters.json")
enc := json.NewEncoder(file)
enc.SetIndent("", " ")
fighters := []Fighter{
{Name: "Son Goku", Power: 9000},
{Name: "Vegeta", Power: 8000},
}
enc.Encode(fighters)
file.Close()
fmt.Println("fighters.json に書き込みました")
// ファイルからJSONを読み込みます。
file, _ = os.Open("fighters.json")
defer file.Close()
var loaded []Fighter
dec := json.NewDecoder(file)
if err := dec.Decode(&loaded); err != nil {
fmt.Println("エラー:", err)
return
}
for _, f := range loaded {
fmt.Printf("Name: %s, Power: %d\n", f.Name, f.Power)
}
os.Remove("fighters.json") // 後始末
}
go run json_encoder_decoder3.go fighters.json に書き込みました Name: Son Goku, Power: 9000 Name: Vegeta, Power: 8000
概要
『Encoder / Decoder』は io.Writer / io.Reader を直接扱うため、HTTPレスポンスやファイルへの書き込み・読み込みをバッファなしで行えます。大きなJSONデータを扱う場合は『json.Marshal / Unmarshal』よりメモリ効率が良いです。
HTTPハンドラーでJSONを返す場合は『json.NewEncoder(w).Encode(data)』が定番のパターンです。『enc.Encode()』は末尾に自動的に改行を追加します。JSONストリームを厳密に制御したい場合はこの点に注意してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。