小编典典

编码为JSON的对象的大小(以位为单位)?

go

我有一个对象。我使用将对象编码为json json.Encoder

我怎样才能测量json字符串的大小?


阅读 400

收藏
2020-07-02

共1个答案

小编典典

io.Writer并且json.Encoder不公开也不维护写入字节数。

一种方法是先使用内置函数json.Marshal()[]byte其编入其长度来封送该值len()。您要查找的位数是长度乘以8(1字节为8位)。之后,您必须手动将字节片写入输出中。对于小型类型,这不是问题,但是对于大型结构/值,可能是不希望的。另外,也没有必要的工作将其编组,获取其长度并手动编写切片。

一种更好,更优雅的方法是使用 embedding
扩展任何作者的功能来管理已写入的字节:

type CounterWr struct {
    io.Writer
    Count int
}

func (cw *CounterWr) Write(p []byte) (n int, err error) {
    n, err = cw.Writer.Write(p)
    cw.Count += n
    return
}

CounterWr类型自动管理其Count字段中的写入字节数,您可以随时对其进行检查/检查。

现在,您创建一个CounterWr传递io.Writer当前使用的的CounterWr值,然后将该值传递给json.NewEncoder(),您可以CounterWr.Count直接从中访问写入的字节数。

用法示例:

type Something struct {
    S string
    I int
}


buf := &bytes.Buffer{}

// Any writer, not just a buffer!
var out io.Writer = buf
cw := &CounterWr{Writer: out}

s := Something{"hello", 4}
if err := json.NewEncoder(cw).Encode(s); err != nil {
    panic(err)
}

fmt.Printf("Count: %d bytes, %d bits\n", cw.Count, cw.Count*8)
fmt.Printf("Verif: %d bytes, %d bits\n", buf.Len(), buf.Len()*8)

为了进行验证,我们还打印了bytes.Buffer用作输出的的长度(CounterWr.Count并且Buffer.Len()应该匹配)。

输出:

Count: 20 bytes, 160 bits
Verif: 20 bytes, 160 bits

Go Playground上尝试一下。

笔记:

如果您也对其他值进行编码,cw.Count则将是当然的总字节数(而不仅仅是最后一个值)。如果只想获取最后一个编码值的大小,请cw.Count在调用之前存储Encoder.Encode(),然后计算与编码后得到的计数之差。或简单地设置cw.Count0编码前(是的,您也可以更改该字段):

cw.Count = 0
2020-07-02