programming

06 How to know JSON Tags

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 becomes first_name in JSON types
  • MiddleName becomes middle_name
  • LastName becomes last_name, and
  • Hobies becomes hobbies

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.
comments powered by Disqus