Go map(string)interface to struct

This article introduces how Golang converts Struct to map[string]interface{}, including the defects of the default method and how to achieve it through other methods.

general method problem

Go usually uses struct to store data, such as storing user information, and may define the following structure:

type UserInfo struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

To convert the structure variable into map[string]interface{}, we can use the json serialization method.

func TestStructToInterface1(t *testing.T) {
	u1 := UserInfo{Name: "q1mi", Age: 18}
	b, _ := json.Marshal(&u1)
	var m map[string]interface{}
	_ = json.Unmarshal(b, &m)
	for k, v := range m{
		fmt.Printf("key:%v value:%v type:%T\n", k, v, v )
	}
}

output result

=== RUN   TestStructToInterface1
key:age value:18 type:float64
key:name value:q1mi type:string
--- PASS: TestStructToInterface1 (0.00s)

It looks normal, but there is a problem. Go’s default json package serialization value type (integer, float, etc.) is float64, not int type. This is obviously not what we expected, so let’s use a third-party package to avoid this problem.

The structs library implements the conversion

Official address of structs: https://github.com/fatih/structs.
Install the package before using: go get github.com/fatih/structs

func TestStructToInterface2(t *testing.T)  {
	u1 := UserInfo{Name: "q1mi", Age: 18}
	m3 := structs.Map(&u1)
	for k, v := range m3 {
		fmt.Printf("key:%v value:%v value type:%T\n", k, v, v)
	}
}

output result

=== RUN   TestStructToInterface2
key:Name value:q1mi value type:string
key:Age value:18 value type:int
--- PASS: TestStructToInterface2 (0.00s)
PASS

There are many other usage examples of structs, readers can check the documentation, the package is currently unmaintained.
structs converts nested structures

We define bodies with nested types:

type UserInfo struct {
	Name string `json:"name" structs:"name"`
	Age  int    `json:"age" structs:"age"`
	Profile `json:"profile" structs:"profile"`
}
// Profile
type Profile struct {
	Hobby string `json:"hobby" structs:"hobby"`
}

test conversion

func TestStructToInterface3(t *testing.T)  {
	u1 := UserInfo{Name: "q1mi", Age: 18, Profile: Profile{"Two Color Ball"}}
	m3 := structs.Map(&u1)
	for k, v := range m3 {
		fmt.Printf("key:%v value:%v value type:%T\n", k, v, v)
	}
}

output result

=== RUN   TestStructToInterface3
key:name value:q1mi value type:string
key:age value:18 value type:int
key:profile value:map[hobby:Two Color Ball] value type:map[string]interface {}
--- PASS: TestStructToInterface3 (0.00s)
PASS

We see that nested structures are mapped as map[string]interface{} types.
Summarize

This article introduces the problem of json serialization, and references the third-party package struts to implement and solve it. In addition, we can also implement it through reflection.

Leave a Reply

Your email address will not be published. Required fields are marked *

en_USEnglish