tubo28's blog
つぼの 140 文字より長い文章置き場
About me

json.Encoder は出力の末尾に改行をつける

Last Modified:
Tags: go

json.Marshal と json.Encoder の微妙な違い

json.Encoder は生成した JSON の末尾に改行を追加します。json.Marshal は追加しません。

以下のコードと出力の通りです。スライスの末尾の 10 に注目。

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
)

func main() {
	m := map[string]string{
		"hello": "world",
	}

	fmt.Println("json.Encoder")
	b := new(bytes.Buffer)
	json.NewEncoder(b).Encode(m)
	fmt.Println("========")
	fmt.Printf("%s\n", b.Bytes())
	fmt.Println("========")
	fmt.Printf("%v\n", b.Bytes())
	fmt.Println("")

	fmt.Println("json.Marshal")
	buf, _ := json.Marshal(m)
	fmt.Println("========" )
	fmt.Printf("%s\n", buf)
	fmt.Println("========")
	fmt.Printf("%v\n", buf)
}
json.Encoder
========
{"hello":"world"}

========
[123 34 104 101 108 108 111 34 58 34 119 111 114 108 100 34 125 10]

json.Marshal
========
{"hello":"world"}
========
[123 34 104 101 108 108 111 34 58 34 119 111 114 108 100 34 125]

どちらも JSON として合法なので、Web API のレスポンスなどとして使う際は問題ありません。

しかし、例えば json.Marshal を使っている関数のテストで、期待する出力を json.Encoder で作ってしまうと微妙にハマるかもしれません。私はハマりました。

理由

json.Encoderio.Writer を引数に取り、TCP ソケットやファイルなどに何度でも書き込める設計です。参考文献の Stack Overflow によると、区切りの改行があると見やすく、また一つの JSON の終わりを改行によって判定できるようになることが理由らしいです。

まぁそうですね。

参考文献