言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

  1. トップページ
  2. Go辞典
  3. json.Encoder / Decoder

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ストリームを厳密に制御したい場合はこの点に注意してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。