Today’s Bug When Doing Custom JSON Marshal in Golang So, today’s bug and a lesson to be learned is about non/pointer receiver function, it happens when I’m doing custom marshal JSON for my struct. I’m stuck for a few hours when to fix this. So the scenario is, I have a struct let’s say a ClassRoom struct, and the ClassRoom has many students. Every student ranked ascending by their mark or something whatever it is :D, this is just an example to describe how is our real case struct. It’s similar, but different in name. type ClassRoom struct { Name string Students map[int]Student } type Students struct { Name string Age int } `json:"name"` `json:"students"` `json:"name"` `json:"age"` With this struct, if we marshall it to JSON, the result will looks like this: { : , : { : { : , : }, : { : , : }, : { : , : } } } "name" "D3TI2-Classmate" "students" "1" "name" "Iman Tumorang" "age" 17 "2" "name" "Christin Tumorang" "age" 18 "3" "name" "Idola Manurung" "age" 18 But for requirement to API, we want the JSON result is without the student’s rank. We just want looks like this: { : , : [ { : , : }, { : , : }, { : , : } ] } "name" "D3TI2-Classmate" "students" "name" "Iman Tumorang" "age" 17 "name" "Christin Tumorang" "age" 18 "name" "Idola Manurung" "age" 18 Well, based on my experience, to do this in Golang is very easy. We just create a function with the ClassRoom as the receiver with the same name as the function name in interface of Marshaler func (s ClassRoom) MarshalJSON() ([]byte, error) { := []Student{} arrKey := []int{} k, := range s.Students { arrKey = append(arrKey, k) } sort.Ints(arrKey) _, := range arrKey { arrStudent = append(arrStudent, s.Students[pos]) } json.Marshal(struct { Name string Students []Student }{ : s.Name, : arrStudent, }) } arrStudent for _ for pos return `json:"name"` `json:"students"` Name Students Just simple as that. But then, when I’m trying to test it. The JSON results is not right as we expected. And I’m stucked for a few hours in this issue :D *so fool I am 😅 Issue Before the code fixed, the code is more like this below. If we see here, it’s like nothing wrong here. But the result is wrong. package main ( ) func main() { := map[int]Student{ : Student{ : , : , }, : Student{ : , : , }, : Student{ : , : , }, } sample := ClassRoom{ : , : students, } jbyt, := json.Marshal(sample) err != nil { log.Fatal(err) } fmt.Println(string(jbyt)) } type ClassRoom struct { Name string Students map[int]Student } type Student struct { Name string Age int } func (s *ClassRoom) MarshalJSON() ([]byte, error) { := []Student{} arrKey := []int{} k, := range s.Students { arrKey = append(arrKey, k) } sort.Ints(arrKey) _, := range arrKey { arrStudent = append(arrStudent, s.Students[pos]) } json.Marshal(struct { Name string Students []Student }{ : arrStudent, : s.Name, }) } import "encoding/json" "fmt" "log" "sort" students 1 Name "Iman Tumorang" Age 17 2 Name "Christin Tumorang" Age 18 3 Name "Idola Manurung" Age 18 Name "D3TI2-Classmate" Students err if `json:"name"` `json:"students"` `json:"name"` `json:"age"` arrStudent for _ for pos return `json:"name"` `json:"students"` Students Name Fixing After tired of searching solutions, then I figured it later when I accidentally call the JSON marshall with a pointer object. sample := &ClassRoom{ Name: , : students, } _,_= json.Marshal(sample) // See the ampersand symbol "&" "D3TI2-Classmate" Students That’s the problem. In my custom MarshalJSON I make the receiver is a pointer. So my custom MarshalJSON won’t called if I try to marshal a non-pointer object. But, if I marshal a non-pointer object, it will succeed to marshal. So to summarize: If I made the custom MarshalJSON with a receiver pointer func (s *ClassRoom)MarshalJSON() ([]byte, error){ } // Other codes Then when I want to marshal the Object, I must pass a object to pointer json.Marhsal sample := &ClassRoom{ Name: , : students, } _,_= json.Marshal(sample) // See the ampersand symbol "&" "D3TI2-Classmate" Students And it also vise versa for receiver. non-pointer (value) func (s ClassRoom)MarshalJSON() ([]byte, error){ } // Other codes If I made the custom MarshalJSON with a receiver non-pointer (value) func (s ClassRoom)MarshalJSON() ([]byte, error){ } // Other codes Then when I want to marshal the Object, I must pass a object to non-pointer (value) json.Marhsal sample := ClassRoom{ Name: , : students, } _,_= json.Marshal(sample) // Without the ampersand symbol "&" "D3TI2-Classmate" Students Well, this is a very silly issue for me, because it’s really made me furious for a few hours. And it’s made me more cautious when deciding using a or receiver in function. pointer non pointer