Introduction to JSON Tags
By default, if we create a struct and marshal it, it will be mapped according to the same attribute name and is case sensitive. So what if we want to differentiate the style between naming attributes in structs and those converted into JSON? For example, in structs we use PascalCase
but in JSON we want to use snake_case
. To support this, the json package supports Tags Reflection, namely tags that can adjust the Json name which we will later convert into JSON so that the tribute in the struct will be converted according to the name into JSON.
Can be understood? OK, we will try to apply and explain further in the next stages below.
type Customer struct {
FirstName string `json:"first_name"`
MiddleName string `json:"middle_name"`
LastName string `json:"last_name"`
Hobbies []string `json:"hobbies"`
}
Actually, at the previous meeting we used Tags Reflection, but we haven’t explained it further. So, we will try to explain tags in more depth at this meeting.
In Struct
above Custumer
on each attribute on the far right there is something like json:"first_name"
. This is what is called Tags Reflection which is when we want to convert from the Customer
struct then the attribute in FirstName
is not named FirstName
(PascalCase) but when it becomes JSON it will follow the tags namely the attribute name first_name
(snake_case).
How to Implement
We will try to create a function which we can use in the previous meeting, namely json
func GenerateobjekJSON(data Customer) string {
bytes, err := json.Marshal(data)
if err != nil {
panic(err)
}
return string(bytes)
}
We will try this function again to convert from struct to type JSON. Just go straight to the unit test which will be seen below.
func TestConvertObjectJSON(t *testing.T) {
type args struct {
data string
}
tests := []struct {
name string
args args
want Customer
}{
{
name: "success conversion object JSON",
args: args{
data: string(`{"first_name":"Santekno","middle_name":"Ihsan","last_name":"Arif","hobbies":["badminton","renang","coding"]}`),
},
want: Customer{
FirstName: "Santekno",
MiddleName: "Ihsan",
LastName: "Arif",
Hobbies: []string{"badminton", "renang", "coding"},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ConvertObjectJSON(tt.args.data); !reflect.DeepEqual(got, tt.want) {
t.Errorf("ConvertObjectJSON() = %v, want %v", got, tt.want)
}
})
}
}
It can be seen that the results of us converting the Customer
struct to JSON are these attributes
FirstName
becomesfirst_name
in JSON typesMiddleName
becomesmiddle_name
LastName
becomeslast_name
, andHobies
becomeshobbies
Likewise, when we change tags that are completely different, it doesn’t matter as long as it complies with JSON type rules so that it can be understood by the Frontend or JSON users.
When using these tags, make sure the type of JSON that we will provide is the same, for example camelCase, snake_case or another style type so that users who will receive this JSON will not have difficulty decoding it.