package main
import (
"encoding/json"
"fmt"
"log"
"reflect"
"strconv"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Age float64 `json:"age"`
IsActive bool `json:"isActive"`
Address *Address `json:"address"`
}
type Address struct {
Street string `json:"street"`
City string `json:"city"`
}
func mapDataToStruct(data map[string]interface{}, target interface{}) error {
v := reflect.ValueOf(target).Elem()
for key, val := range data {
field := v.FieldByName(key)
if !field.IsValid() {
log.
Printf("Warning: Invalid key in data: %s", key
) continue
}
if !field.CanSet() {
return fmt.Errorf("field '%s' is not settable", key)
}
rv := reflect.ValueOf(val)
// Check and initialize pointer fields
if field.Kind() == reflect.Ptr {
if field.IsNil() { // Safe alternative to IsZero
field.Set(reflect.New(field.Type().Elem()))
}
field = field.Elem()
}
switch field.Kind() {
case reflect.Int:
switch v := rv.Interface().(type) {
case float64:
field.SetInt(int64(v))
case string:
i, err := strconv.Atoi(v)
if err != nil {
return fmt.Errorf("error converting to int for field '%s': %v", key, err)
}
field.SetInt(int64(i))
case int:
field.SetInt(int64(v))
default:
return fmt.Errorf("invalid type for field '%s': expected int, got %T", key, val)
}
case reflect.Float64:
switch v := rv.Interface().(type) {
case float64:
field.SetFloat(v)
case string:
f, err := strconv.ParseFloat(v, 64)
if err != nil {
return fmt.Errorf("error converting to float64 for field '%s': %v", key, err)
}
field.SetFloat(f)
case int:
field.SetFloat(float64(v))
default:
return fmt.Errorf("invalid type for field '%s': expected float64, got %T", key, val)
}
case reflect.String:
if s, ok := rv.Interface().(string); ok {
field.SetString(s)
} else {
return fmt.Errorf("invalid type for field '%s': expected string, got %T", key, val)
}
case reflect.Bool:
switch v := rv.Interface().(type) {
case bool:
field.SetBool(v)
case string:
b, err := strconv.ParseBool(v)
if err != nil {
return fmt.Errorf("error converting to bool for field '%s': %v", key, err)
}
field.SetBool(b)
default:
return fmt.Errorf("invalid type for field '%s': expected bool, got %T", key, val)
}
case reflect.Struct:
if nestedMap, ok := val.(map[string]interface{}); ok {
if err := mapDataToStruct(nestedMap, field.Addr().Interface()); err != nil {
return err
}
} else {
return fmt.Errorf("invalid type for field '%s': expected map for nested struct, got %T", key, val)
}
default:
return fmt.Errorf("unsupported field type for '%s': %s", key, field.Kind())
}
}
return nil
}
func main() {
inputData := map[string]interface{}{
"id": 1,
"name": "Abak",
"age": 25.6,
"isActive": true,
"address": map[string]interface{}{
"street": "Bashundhara",
"city": "Dhaka",
},
"gender": "male", // Unsupported field
}
var user User
if err := mapDataToStruct(inputData, &user); err != nil {
log.
Fatalf("Error mapping data: %v", err
) }
jsonData, err := json.MarshalIndent(user, "", " ")
if err != nil {
log.
Fatalf("Error marshaling JSON: %v", err
) }
fmt.Println("User data after mapping:")
fmt.Println(string(jsonData))
}
cGFja2FnZSBtYWluCgppbXBvcnQgKAoJImVuY29kaW5nL2pzb24iCgkiZm10IgoJImxvZyIKCSJyZWZsZWN0IgoJInN0cmNvbnYiCikKCnR5cGUgVXNlciBzdHJ1Y3QgewoJSUQgICAgICAgaW50ICAgICAgYGpzb246ImlkImAKCU5hbWUgICAgIHN0cmluZyAgIGBqc29uOiJuYW1lImAKCUFnZSAgICAgIGZsb2F0NjQgIGBqc29uOiJhZ2UiYAoJSXNBY3RpdmUgYm9vbCAgICAgYGpzb246ImlzQWN0aXZlImAKCUFkZHJlc3MgICpBZGRyZXNzIGBqc29uOiJhZGRyZXNzImAKfQoKdHlwZSBBZGRyZXNzIHN0cnVjdCB7CglTdHJlZXQgc3RyaW5nIGBqc29uOiJzdHJlZXQiYAoJQ2l0eSAgIHN0cmluZyBganNvbjoiY2l0eSJgCn0KCmZ1bmMgbWFwRGF0YVRvU3RydWN0KGRhdGEgbWFwW3N0cmluZ11pbnRlcmZhY2V7fSwgdGFyZ2V0IGludGVyZmFjZXt9KSBlcnJvciB7Cgl2IDo9IHJlZmxlY3QuVmFsdWVPZih0YXJnZXQpLkVsZW0oKQoKCWZvciBrZXksIHZhbCA6PSByYW5nZSBkYXRhIHsKCQlmaWVsZCA6PSB2LkZpZWxkQnlOYW1lKGtleSkKCQlpZiAhZmllbGQuSXNWYWxpZCgpIHsKCQkJbG9nLlByaW50ZigiV2FybmluZzogSW52YWxpZCBrZXkgaW4gZGF0YTogJXMiLCBrZXkpCgkJCWNvbnRpbnVlCgkJfQoKCQlpZiAhZmllbGQuQ2FuU2V0KCkgewoJCQlyZXR1cm4gZm10LkVycm9yZigiZmllbGQgJyVzJyBpcyBub3Qgc2V0dGFibGUiLCBrZXkpCgkJfQoKCQlydiA6PSByZWZsZWN0LlZhbHVlT2YodmFsKQoKCQkvLyBDaGVjayBhbmQgaW5pdGlhbGl6ZSBwb2ludGVyIGZpZWxkcwoJCWlmIGZpZWxkLktpbmQoKSA9PSByZWZsZWN0LlB0ciB7CgkJCWlmIGZpZWxkLklzTmlsKCkgeyAvLyBTYWZlIGFsdGVybmF0aXZlIHRvIElzWmVybwoJCQkJZmllbGQuU2V0KHJlZmxlY3QuTmV3KGZpZWxkLlR5cGUoKS5FbGVtKCkpKQoJCQl9CgkJCWZpZWxkID0gZmllbGQuRWxlbSgpCgkJfQoKCQlzd2l0Y2ggZmllbGQuS2luZCgpIHsKCQljYXNlIHJlZmxlY3QuSW50OgoJCQlzd2l0Y2ggdiA6PSBydi5JbnRlcmZhY2UoKS4odHlwZSkgewoJCQljYXNlIGZsb2F0NjQ6CgkJCQlmaWVsZC5TZXRJbnQoaW50NjQodikpCgkJCWNhc2Ugc3RyaW5nOgoJCQkJaSwgZXJyIDo9IHN0cmNvbnYuQXRvaSh2KQoJCQkJaWYgZXJyICE9IG5pbCB7CgkJCQkJcmV0dXJuIGZtdC5FcnJvcmYoImVycm9yIGNvbnZlcnRpbmcgdG8gaW50IGZvciBmaWVsZCAnJXMnOiAldiIsIGtleSwgZXJyKQoJCQkJfQoJCQkJZmllbGQuU2V0SW50KGludDY0KGkpKQoJCQljYXNlIGludDoKCQkJCWZpZWxkLlNldEludChpbnQ2NCh2KSkKCQkJZGVmYXVsdDoKCQkJCXJldHVybiBmbXQuRXJyb3JmKCJpbnZhbGlkIHR5cGUgZm9yIGZpZWxkICclcyc6IGV4cGVjdGVkIGludCwgZ290ICVUIiwga2V5LCB2YWwpCgkJCX0KCQljYXNlIHJlZmxlY3QuRmxvYXQ2NDoKCQkJc3dpdGNoIHYgOj0gcnYuSW50ZXJmYWNlKCkuKHR5cGUpIHsKCQkJY2FzZSBmbG9hdDY0OgoJCQkJZmllbGQuU2V0RmxvYXQodikKCQkJY2FzZSBzdHJpbmc6CgkJCQlmLCBlcnIgOj0gc3RyY29udi5QYXJzZUZsb2F0KHYsIDY0KQoJCQkJaWYgZXJyICE9IG5pbCB7CgkJCQkJcmV0dXJuIGZtdC5FcnJvcmYoImVycm9yIGNvbnZlcnRpbmcgdG8gZmxvYXQ2NCBmb3IgZmllbGQgJyVzJzogJXYiLCBrZXksIGVycikKCQkJCX0KCQkJCWZpZWxkLlNldEZsb2F0KGYpCgkJCWNhc2UgaW50OgoJCQkJZmllbGQuU2V0RmxvYXQoZmxvYXQ2NCh2KSkKCQkJZGVmYXVsdDoKCQkJCXJldHVybiBmbXQuRXJyb3JmKCJpbnZhbGlkIHR5cGUgZm9yIGZpZWxkICclcyc6IGV4cGVjdGVkIGZsb2F0NjQsIGdvdCAlVCIsIGtleSwgdmFsKQoJCQl9CgkJY2FzZSByZWZsZWN0LlN0cmluZzoKCQkJaWYgcywgb2sgOj0gcnYuSW50ZXJmYWNlKCkuKHN0cmluZyk7IG9rIHsKCQkJCWZpZWxkLlNldFN0cmluZyhzKQoJCQl9IGVsc2UgewoJCQkJcmV0dXJuIGZtdC5FcnJvcmYoImludmFsaWQgdHlwZSBmb3IgZmllbGQgJyVzJzogZXhwZWN0ZWQgc3RyaW5nLCBnb3QgJVQiLCBrZXksIHZhbCkKCQkJfQoJCWNhc2UgcmVmbGVjdC5Cb29sOgoJCQlzd2l0Y2ggdiA6PSBydi5JbnRlcmZhY2UoKS4odHlwZSkgewoJCQljYXNlIGJvb2w6CgkJCQlmaWVsZC5TZXRCb29sKHYpCgkJCWNhc2Ugc3RyaW5nOgoJCQkJYiwgZXJyIDo9IHN0cmNvbnYuUGFyc2VCb29sKHYpCgkJCQlpZiBlcnIgIT0gbmlsIHsKCQkJCQlyZXR1cm4gZm10LkVycm9yZigiZXJyb3IgY29udmVydGluZyB0byBib29sIGZvciBmaWVsZCAnJXMnOiAldiIsIGtleSwgZXJyKQoJCQkJfQoJCQkJZmllbGQuU2V0Qm9vbChiKQoJCQlkZWZhdWx0OgoJCQkJcmV0dXJuIGZtdC5FcnJvcmYoImludmFsaWQgdHlwZSBmb3IgZmllbGQgJyVzJzogZXhwZWN0ZWQgYm9vbCwgZ290ICVUIiwga2V5LCB2YWwpCgkJCX0KCQljYXNlIHJlZmxlY3QuU3RydWN0OgoJCQlpZiBuZXN0ZWRNYXAsIG9rIDo9IHZhbC4obWFwW3N0cmluZ11pbnRlcmZhY2V7fSk7IG9rIHsKCQkJCWlmIGVyciA6PSBtYXBEYXRhVG9TdHJ1Y3QobmVzdGVkTWFwLCBmaWVsZC5BZGRyKCkuSW50ZXJmYWNlKCkpOyBlcnIgIT0gbmlsIHsKCQkJCQlyZXR1cm4gZXJyCgkJCQl9CgkJCX0gZWxzZSB7CgkJCQlyZXR1cm4gZm10LkVycm9yZigiaW52YWxpZCB0eXBlIGZvciBmaWVsZCAnJXMnOiBleHBlY3RlZCBtYXAgZm9yIG5lc3RlZCBzdHJ1Y3QsIGdvdCAlVCIsIGtleSwgdmFsKQoJCQl9CgkJZGVmYXVsdDoKCQkJcmV0dXJuIGZtdC5FcnJvcmYoInVuc3VwcG9ydGVkIGZpZWxkIHR5cGUgZm9yICclcyc6ICVzIiwga2V5LCBmaWVsZC5LaW5kKCkpCgkJfQoJfQoJcmV0dXJuIG5pbAp9CgpmdW5jIG1haW4oKSB7CglpbnB1dERhdGEgOj0gbWFwW3N0cmluZ11pbnRlcmZhY2V7fXsKCQkiaWQiOiAgICAgICAxLAoJCSJuYW1lIjogICAgICJBYmFrIiwKCQkiYWdlIjogICAgICAyNS42LAoJCSJpc0FjdGl2ZSI6IHRydWUsCgkJImFkZHJlc3MiOiBtYXBbc3RyaW5nXWludGVyZmFjZXt9ewoJCQkic3RyZWV0IjogIkJhc2h1bmRoYXJhIiwKCQkJImNpdHkiOiAgICJEaGFrYSIsCgkJfSwKCQkiZ2VuZGVyIjogIm1hbGUiLCAvLyBVbnN1cHBvcnRlZCBmaWVsZAoJfQoKCXZhciB1c2VyIFVzZXIKCWlmIGVyciA6PSBtYXBEYXRhVG9TdHJ1Y3QoaW5wdXREYXRhLCAmdXNlcik7IGVyciAhPSBuaWwgewoJCWxvZy5GYXRhbGYoIkVycm9yIG1hcHBpbmcgZGF0YTogJXYiLCBlcnIpCgl9CgoJanNvbkRhdGEsIGVyciA6PSBqc29uLk1hcnNoYWxJbmRlbnQodXNlciwgIiIsICIgICIpCglpZiBlcnIgIT0gbmlsIHsKCQlsb2cuRmF0YWxmKCJFcnJvciBtYXJzaGFsaW5nIEpTT046ICV2IiwgZXJyKQoJfQoJZm10LlByaW50bG4oIlVzZXIgZGF0YSBhZnRlciBtYXBwaW5nOiIpCglmbXQuUHJpbnRsbihzdHJpbmcoanNvbkRhdGEpKQp9Cg==