I write A
object to a file f
.
a := A{42}
bytes, _ := json.MarshalIndent(a, "", "\t")
f.Write(bytes)
Where A
looks like:
type A struct {
A int `json:"a"`
}
Then I change field of this object and write it to the file:
a.A = 666
f.Write(bytes)
As a result, I see only
{
"a": 42
}{
"a": 42
}
While I expected:
{
"a": 42
}{
"a": 666
}
I know that I can overcome it by using json.MarshalIndent
again. But I need to do a lot of (~10^6) writings to the file, so using json.MarshalIndent
again and again seems to be a heavy task.
How can I directly change a bytes
variable?
Code is located at https://play.golang.org/p/8CMpwehMidR
You have no choice but to marshal repeatedly. Use a *json.Encoder for improved ergonomics and efficiency:
package main
import (
"encoding/json"
"log"
"os"
)
type A struct {
A int `json:"a"`
}
func main() {
f, err := os.Create("foo.json")
if err != nil {
log.Fatal(err)
}
defer f.Close()
enc := json.NewEncoder(f)
enc.SetIndent("", "\t")
a := A{42} // Using a pointer may improve performance if A is large.
enc.Encode(a)
a.A = 666
enc.Encode(a)
}
Wrapping the file with a buffered writer may also improve performance, depending on how quickly you can compute successive values for the As and how fast the disk is.
you can use the standard library to replace bytes within the given bytes slice.
https://golang.org/pkg/bytes/#Replace
package main
import (
"bufio"
"bytes"
"encoding/json"
"os"
)
type A struct {
A int `json:"a"`
}
func main() {
out := bufio.NewWriterSize(os.Stdout, 20)
// defer out.Flush() // commented for demonstration purpose. Uncomment this to finalize the flush.
a := A{42}
b, _ := json.MarshalIndent(a, "", "\t")
out.Write(b)
b = bytes.Replace(b, []byte("42"), []byte("666"), -1)
out.Write(b)
}
It is not recommended to do it, but ultimately this is possible.
I included a buffered writer for demonstration of others answers and comments, don t forget to flush it.