Searches like golang map to struct, golang convert map to struct, map to struct golang, and go map to struct all ask how to fill typed fields from a loose map[string]any (older code often wrote map[string]interface{} — the same idea). Converting map string interface to struct is common after json.Unmarshal into a generic map, or when reading dynamic config. This page shows encoding/json, mapstructure, a small for loop, and a minimal reflect sketch, then briefly covers convert struct to map golang. For map-only JSON paths, see map to JSON in Go and JSON unmarshal in Go.
Tested with Go 1.24 on Linux.
Convert map[string]any to a struct (map to struct golang)
Pick a strategy that matches where the map came from and how strict you want decoding to be.
JSON roundtrip with json.Marshal and json.Unmarshal
If map keys line up with json tags (often lowercase wire names), marshaling to JSON and unmarshaling into the struct is simple and stays in the standard library:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Address string `json:"address"`
}
func main() {
m := map[string]any{
"name": "Amit Kumar",
"age": 30,
"address": "316 Some Main Road, Cruasia",
}
b, err := json.Marshal(m)
if err != nil {
fmt.Println("marshal:", err)
return
}
var out Person
if err := json.Unmarshal(b, &out); err != nil {
fmt.Println("unmarshal:", err)
return
}
fmt.Printf("%+v\n", out)
}You should see the struct populated with the three fields. This pattern is the default answer for convert map to struct golang when values are JSON-serializable.
mapstructure for nested maps and loose shapes
For golang map string interface to struct when you want direct decode without a JSON hop, or nested map[string]any values mapped into nested structs, mapstructure is a common choice. Run it locally after go get github.com/mitchellh/mapstructure (the in-site Run button cannot fetch this module).
package main
import (
"fmt"
"github.com/mitchellh/mapstructure"
)
type Person struct {
Name string
Age int
Address map[string]string
}
func main() {
m := map[string]any{
"Name": "Amit Kumar",
"Age": 30,
"Address": map[string]string{
"street": "316 Some Main Road",
"city": "Crusasia",
"state": "Karnataka",
"zip": "803471",
},
}
var out Person
if err := mapstructure.Decode(m, &out); err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v\n", out)
}You should see Name, Age, and the nested Address map filled. For stricter decoding (for example surfacing unexpected keys), configure mapstructure.DecoderConfig instead of the one-line Decode.
Manual field copy with a for loop or switch
When the struct is tiny and keys are fixed, explicit conversion avoids magic and keeps dependencies at zero:
package main
import "fmt"
type Identity struct {
Name string
Age int
}
func main() {
m := map[string]any{
"Name": "Amit Kumar",
"Age": 30,
}
var p Identity
for k, v := range m {
switch k {
case "Name":
p.Name = v.(string)
case "Age":
p.Age = v.(int)
}
}
fmt.Printf("%+v\n", p)
}You should see {Name:Amit Kumar Age:30}. Type assertions panic if the dynamic type is wrong; production code should use the two-value form or fmt.Sscanf-style parsing depending on the source.
Reflection (advanced, easy to break)
reflect can walk exported struct fields and look up keys by field name. It only works cleanly when map values are already assignable to the field types — otherwise Set panics (for example float64 from JSON into an int field):
package main
import (
"fmt"
"reflect"
)
type Identity struct {
Name string
Age int
}
func fillFromMap(m map[string]any, dst any) {
v := reflect.ValueOf(dst).Elem()
t := v.Type()
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if val, ok := m[f.Name]; ok {
v.Field(i).Set(reflect.ValueOf(val))
}
}
}
func main() {
m := map[string]any{"Name": "Amit Kumar", "Age": 30}
var p Identity
fillFromMap(m, &p)
fmt.Printf("%+v\n", p)
}Prefer encoding/json or mapstructure once types might not match exactly.
Convert struct to map golang
The symmetric move — struct to loose map — is often done with a JSON hop so json tags become keys:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
p := Person{Name: "Ada", Age: 40}
b, err := json.Marshal(p)
if err != nil {
fmt.Println(err)
return
}
var m map[string]any
if err := json.Unmarshal(b, &m); err != nil {
fmt.Println(err)
return
}
fmt.Println(m["name"], m["age"])
}You should see Ada and 40 (the number may print as a float64 wire form depending on formatting; it is still the right logical value). Building the map by hand is fine when the struct is small and you control the key names.
Summary
For golang map to struct work, json.Marshal followed by json.Unmarshal into a tagged struct is the usual default for convert map to struct golang when keys already look like JSON. golang map string interface to struct scenarios with odd key names or nested dynamic data often fit mapstructure better than hand-rolled reflect. A manual for loop stays readable for very small structs. For convert struct to map golang, marshal the struct to JSON and unmarshal into map[string]any, or assign fields explicitly. Always handle marshal and unmarshal errors in real programs.
References
- Package json
- mapstructure
- Package reflect —
Value,Type,Set - Map to JSON in Go
- JSON unmarshal in Go

