json.Encoder
似乎与json.Marshal
略有不同。具体来说,它在编码值的末尾添加一个新行。知道为什么会这样吗?对我来说这看起来像个错误。
package main
import "fmt"
import "encoding/json"
import "bytes"
func main() {
var v string
v = "hello"
buf := bytes.NewBuffer(nil)
json.NewEncoder(buf).Encode(v)
b, _ := json.Marshal(&v)
fmt.Printf("%q, %q", buf.Bytes(), b)
}
此输出
"\"hello\"\n", "\"hello\""
答案 0 :(得分:5)
因为他们在使用Encoder.Encode
时明确添加了新的字符。这是该func的源代码,它实际上表明它在文档中添加了换行符(参见注释,这是文档):
https://golang.org/src/encoding/json/stream.go?s=4272:4319#L173
// Encode writes the JSON encoding of v to the stream,
// followed by a newline character.
//
// See the documentation for Marshal for details about the
// conversion of Go values to JSON.
func (enc *Encoder) Encode(v interface{}) error {
if enc.err != nil {
return enc.err
}
e := newEncodeState()
err := e.marshal(v)
if err != nil {
return err
}
// Terminate each value with a newline.
// This makes the output look a little nicer
// when debugging, and some kind of space
// is required if the encoded value was a number,
// so that the reader knows there aren't more
// digits coming.
e.WriteByte('\n')
if _, err = enc.w.Write(e.Bytes()); err != nil {
enc.err = err
}
encodeStatePool.Put(e)
return err
}
现在,为什么Go开发人员除了“使输出看起来有点好”之外还做了什么呢?一个答案:
go json Encoder
针对流进行了优化(例如json数据的MB / GB / PB)。通常,在流式传输时,您需要一种方法来消除流完成的时间。对于Encoder.Encode()
,这是一个\n
换行符。当然,你当然可以写入缓冲区。但是你也可以写一个io.Writer来传输v
的块。
这与使用json.Marshal
相反,如果您的输入来自不受信任(且未知的有限)来源(例如,ajax POST方法到您的Web服务 - 如果有人发布了100MB json,那么通常不鼓励使用json.Marshal
文件?)。并且,Marshal
将是json的最终完整集合 - 例如你不希望将几个\gb
个条目连在一起。您可以使用Encoder.Encode()来构建一个大型集合并写入缓冲区,流,文件,io.Writer等。
每当怀疑它是否是一个bug时,我总是查找源代码 - 这是Go的优点之一,它的源代码和编译器只是纯粹的Go。在[n] vim中,我使用/usr/lib/kscreenlocker_greet --testing
在my .vimrc
settings的浏览器中打开源定义。
答案 1 :(得分:0)
Encoder写入值流。额外的空格是值之间的分隔符。
答案 2 :(得分:0)
您可以通过反向流擦除换行符:
f, _ := os.OpenFile(fname, ...)
encoder := json.NewEncoder(f)
encoder.Encode(v)
f.Seek(-1, 1)
f.WriteString("other data ...")
他们应该让用户控制这种奇怪的行为: