Skip to content

Instantly share code, notes, and snippets.

@bxcodec
Last active July 31, 2024 21:43
Show Gist options
  • Save bxcodec/c2a25cfc75f6b21a0492951706bc80b8 to your computer and use it in GitHub Desktop.
Save bxcodec/c2a25cfc75f6b21a0492951706bc80b8 to your computer and use it in GitHub Desktop.
Golang Struct To Map Example By JSON tag
/*
This function will help you to convert your object from struct to map[string]interface{} based on your JSON tag in your structs.
Example how to use posted in sample_test.go file.
*/
func structToMap(item interface{}) map[string]interface{} {
res := map[string]interface{}{}
if item == nil {
return res
}
v := reflect.TypeOf(item)
reflectValue := reflect.ValueOf(item)
reflectValue = reflect.Indirect(reflectValue)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
for i := 0; i < v.NumField(); i++ {
tag := v.Field(i).Tag.Get("json")
field := reflectValue.Field(i).Interface()
if tag != "" && tag != "-" {
if v.Field(i).Type.Kind() == reflect.Struct {
res[tag] = structToMap(field)
} else {
res[tag] = field
}
}
}
return res
}
package sample_test
import (
"encoding/json"
"fmt"
"testing"
"github.com/stretchr/testify/require"
)
type SampleStruct struct {
Name string `json:"name"`
ID string `json:"id"`
}
type EmbededStruct struct {
FieldStruct `json:"field"`
Hello string `json:"hello"`
}
type FieldStruct struct {
OnePoint string `json:"one_point"`
Sample *SampleStruct `json:"sample"`
}
func TestStructToMap_Normal(t *testing.T) {
sample := SampleStruct{
Name: "John Doe",
ID: "12121",
}
res := structToMap(sample)
require.NotNil(t, res)
fmt.Printf("%+v \n", res)
// Output: map[name:John Doe id:12121]
jbyt, err := json.Marshal(res)
require.NoError(t, err)
fmt.Println(string(jbyt))
// Output: {"id":"12121","name":"John Doe"}
}
func TestStructToMap_FieldStruct(t *testing.T) {
sample := &SampleStruct{
Name: "John Doe",
ID: "12121",
}
field := FieldStruct{
Sample: sample,
OnePoint: "yuhuhuu",
}
res := structToMap(field)
require.NotNil(t, res)
fmt.Printf("%+v \n", res)
// Output: map[sample:0xc4200f04a0 one_point:yuhuhuu]
jbyt, err := json.Marshal(res)
require.NoError(t, err)
fmt.Println(string(jbyt))
// Output: {"one_point":"yuhuhuu","sample":{"name":"John Doe","id":"12121"}}
}
func TestStructToMap_EmbeddedStruct(t *testing.T) {
sample := &SampleStruct{
Name: "John Doe",
ID: "12121",
}
field := FieldStruct{
Sample: sample,
OnePoint: "yuhuhuu",
}
embed := EmbededStruct{
FieldStruct: field,
Hello: "WORLD!!!!",
}
res := structToMap(embed)
require.NotNil(t, res)
fmt.Printf("%+v \n", res)
//Output: map[field:map[one_point:yuhuhuu sample:0xc420106420] hello:WORLD!!!!]
jbyt, err := json.Marshal(res)
require.NoError(t, err)
fmt.Println(string(jbyt))
// Output: {"field":{"one_point":"yuhuhuu","sample":{"name":"John Doe","id":"12121"}},"hello":"WORLD!!!!"}
}
@junaid-ali
Copy link

@ahmadissa I'm using the similar approach but I was wondering if we could directly convert struct to map without involving []byte

@vashish1
Copy link

This will also fail, if the json tag includes "omitempty"

for example:
type User struct {
Uid string json:"uid,omitempty"
Name string json:"name,omitempty"
Email string json:"email,omitempty"
Mobile_no string json:"mobile_no,omitempty"
Shortlisted []ShortList json:"shortlisted,omitempty"
}

the resulted json key insuch case will be mobile_no,omitempty

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment