I have an object. I encode the object to json using json.Encoder
.
How can I measure the size of the json string in either bits?
I have an object. I encode the object to json using json.Encoder
.
How can I measure the size of the json string in either bits?
io.Writer
and json.Encoder
does not expose nor maintain number of written bytes.
One way would be to first marshal the value using json.Marshal()
into a []byte
whose length we can get with the builtin len()
function. The bit count you seek for is the length multiplied by 8 (1 byte is 8 bits). After that you have to manually write the byte slice to your output. For small types, this is not a problem, but it may be undesirable for large structs / values. Also there is unnecessary work marshalling it, getting its length and writing the slice manually.
A much better and more elegant way is to extend the functionality of any writers to manage the written bytes, using 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
}
This CounterWr
type automatically manages the number of written bytes in its Count
field which you can check / examine at any time.
Now you create a value of our CounterWr
passing the io.Writer
that you currently use, and then pass this CounterWr
value to json.NewEncoder()
, and you can access number of written bytes from CounterWr.Count
directly.
Example usage:
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)
For verification purposes we're also printing the length of the bytes.Buffer
we used as our output (CounterWr.Count
and Buffer.Len()
should match).
Output:
Count: 20 bytes, 160 bits
Verif: 20 bytes, 160 bits
Try it on the Go Playground.
Notes:
If you encode other values too, cw.Count
will be the number of total bytes of course (and not just that of the last value). If you want to get the size of the last encoded value only, store cw.Count
before calling Encoder.Encode()
, and calculate the difference to the count you get after encoding it. Or simply set cw.Count
to 0
before encoding (yes, you can also change that field):
cw.Count = 0