fastjson
fastjson copied to clipboard
MarshalTo doesn't actually append to the passed in slice
func TestMarshalTo(t *testing.T) {
var p fastjson.Parser
v, err := p.Parse(`{
"str": "bar",
"int": 123,
"float": 1.23,
"bool": true,
"arr": [1, "foo", {}]
}`)
if err != nil {
log.Fatal(err)
}
out := make([]byte, 0, 50000)
log.Println(string(v.MarshalTo(out)))
log.Println(string(out))
}
2019/01/24 12:15:45: {"str":"bar","int":123,"float":1.23,"bool":true,"arr":[1,"foo",{}]}
2019/01/24 12:15:45:
You are returning a newly appended slice instead of attempting to append to the passed in slice. Passed in slice needs to be *[]byte for it to work as I think you have intended.
Or you can just copy() instead of append as append will cause allocations if the slice isn't large enough.
MarshalTo must append data to the passed in slice. Just len(out) = 0 in the code above, so its' length must be extended before comparison. Try running the following code:
out := make([]byte, 0, 50000)
outNew := v.MarshalTo(out)
// Verify whether MarshalTo added data to out or put it to another memory
outExtended := out[:len(outNew)]
if bytes.Equal(outNew, outExtended) {
log.Println("outNew points to out memory")
} else {
log.Println("outNew points to another memory")
}
See https://blog.golang.org/go-slices-usage-and-internals to understand better how slices in Go work
Are you saying the proper use case for MarshalTo should then be.
out := make([]byte, 0, 50000) //or some other form of pre-allocation
out = v.MarshalTo(out)
The proper use case for MarshalTo is:
// The out slice is defined once and re-used multiple times
// inside the loop for marshaling different values.
var out []byte
for {
// obtain v here
out = v.MarshalTo(out[:0])
// use out here
}
:+1: thanks