If you like to see the video on this blog, then here is the link of the video:
Go: Efficient Marshalling & Unmarshalling | SONIC | JSON — YouTube

As a developer it is our day-to-day job converting the data from the byte type (received from the network wire in the form of response) to your API response struct. In this blog we will see how we can do that efficiently and in a optimized manner(consume low CPU and Memory)
I will compare two libraries, SONIC and JSON and will perform the benchmark test for these two libraries and check which is optimal for our use case.
Test Criteria:
The payload is divided into three parts.
1. Small size struct
2. Medium size struct
3. Large size struct
4. Extra Large size struct
About the operation:
It will consist a method which is performing two operations, first marshalling and then unmarshalling.
func MarshallingUnmarshallingJSON(t1 []album) {
var result []*album
byteReponse, _ := json.Marshal(t1)
json.Unmarshal(byteReponse, &result)
}
func MarshallingUnmarshallingSONIC(t1 []album) {
var result []album
byteReponse, _ := sonic.Marshal(t1)
sonic.Unmarshal(byteReponse, &result)
}
Result array size lies in four categories, and the benchmark result is as follows:
func BenchmarkJSON(b *testing.B) {
// Small, Medium, Large, Extra Large
var input = []int{10, 50, 100, 400}
for _, v := range input {
albums := BuildResponse(v)
b.Run(fmt.Sprintf("input_size_%d", v), func(b *testing.B) {
for i := 0; i < b.N; i++ {
MarshallingUnmarshallingJSON(albums)
}
})
}
}
func BenchmarkSonic(b *testing.B) {
// Small, Medium, Large, Extra Large
var input = []int{10, 50, 100, 400}
for _, v := range input {
albums := BuildResponse(v)
b.Run(fmt.Sprintf("input_size_%d", v), func(b *testing.B) {
for i := 0; i < b.N; i++ {
MarshallingUnmarshallingSONIC(albums)
}
})
}
}
And the results after benchmark test are as follows:

In all dimensions, SONIC is the clear winner and recommended for the use as it saves your memory and CPU.