为了账号安全,请及时绑定邮箱和手机立即绑定

为什么 json.Encoder 多加一行?

为什么 json.Encoder 多加一行?

Go
小唯快跑啊 2021-12-27 18:26:23
json.Encoder似乎与json.Marshal. 具体来说,它在编码值的末尾添加了一个新行。知道这是为什么吗?对我来说这看起来像是一个错误。package mainimport "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\""
查看完整描述

3 回答

?
忽然笑

TA贡献1806条经验 获得超5个赞

因为他们在使用Encoder.Encode. 这是该函数的源代码,它实际上声明它在文档中添加了一个换行符(请参阅注释,这是文档):


https://golang.org/src/encoding/json/stream.go?s=4272:4319


// 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 jsonEncoder针对流进行了优化(例如 json 数据的 MB/GB/PB)。通常,在流式传输时,您需要一种方法来确定流何时完成。在 的情况下Encoder.Encode(),这是一个\n换行符。当然,您当然可以写入缓冲区。但是你也可以写入一个 io.Writer ,它会流式传输v.


这与json.Marshal如果您的输入来自不受信任(且未知受限)的来源(例如,对您的 Web 服务的 ajax POST 方法 - 如果有人发布 100MB json 文件怎么办?)的使用通常是不鼓励的。并且,json.Marshal将是最终完整的 json 集 - 例如,您不会期望将 100Marshal个条目连接在一起。您将使用 Encoder.Encode() 来构建一个大集合并写入缓冲区、流、文件、io.Writer 等。


每当怀疑它是否是一个错误时,我总是查找源代码 - 这是 Go 的优势之一,它的源代码和编译器只是纯粹的 Go。在 [n]vim 中,我使用我的设置\gb在浏览器中打开源定义。.vimrc


查看完整回答
反对 回复 2021-12-27
?
隔江千里

TA贡献1906条经验 获得超10个赞

您可以通过向后流擦除换行符:


f, _ := os.OpenFile(fname, ...)

encoder := json.NewEncoder(f)

encoder.Encode(v)

f.Seek(-1, 1)

f.WriteString("other data ...")

他们应该让用户控制这种奇怪的行为:

  • 禁用它的构建选项

  • Encoder.SetEOF(eof 字符串)

  • Encoder.SetIndent(前缀,缩进,eof 字符串)


查看完整回答
反对 回复 2021-12-27
?
holdtom

TA贡献1805条经验 获得超10个赞

编码器写入文件流。额外的空格终止流中的 JSON 文档。

流读取器需要终止符。考虑一个包含以下 JSON 文档的流:123. 如果没有额外的空格,线路上的数据就是字节序列123。这是一个编号为 123 的 JSON 文档,而不是三个文档。


查看完整回答
反对 回复 2021-12-27
  • 3 回答
  • 0 关注
  • 456 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信