package main
import (
"fmt"
"log"
"reflect"
"strconv"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Height float64 `json:"height"`
IsStudent bool `json:"is_student"`
Address Address `json:"address"`
}
type Address struct {
City string `json:"city"`
Zip int `json:"zip"`
}
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("Invalid key in data: %s", key
) continue
}
if !field.CanSet() {
return fmt.Errorf("Field '%s' is not settable", key)
}
typ := field.Type()
// Handling nested structs (e.g., Address)
if typ.Kind() == reflect.Struct && reflect.ValueOf(val).Kind() == reflect.Map {
if err := mapDataToStruct(val.(map[string]interface{}), field.Addr().Interface()); err != nil {
return err
}
continue
}
switch v := val.(type) {
case string:
switch typ.Kind() {
case reflect.Int:
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 reflect.Float64:
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 reflect.Bool:
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:
field.SetString(v)
}
case int:
if typ.Kind() == reflect.Float64 {
field.SetFloat(float64(v))
} else {
field.SetInt(int64(v))
}
case float64:
if typ.Kind() == reflect.Int {
field.SetInt(int64(v))
} else {
field.SetFloat(v)
}
case bool:
field.SetBool(v)
default:
return fmt.Errorf("Unsupported type for field '%s': %T", key, val)
}
}
return nil
}
func main() {
inputData := map[string]interface{}{
"name": "Jenny Doe",
"age": 28,
"height": 1.65,
"is_student": true,
"address": map[string]interface{}{
"city": "San Francisco",
"zip": 94102,
},
"gender": "female", // Unsupported field
}
var person Person
if err := mapDataToStruct(inputData, &person); err != nil {
log.
Fatalf("Error mapping data: %v", err
) }
fmt.Printf("Person after mapping: %+v\n", person)
}
cGFja2FnZSBtYWluCgppbXBvcnQgKAoJImZtdCIKCSJsb2ciCgkicmVmbGVjdCIKCSJzdHJjb252IgopCgp0eXBlIFBlcnNvbiBzdHJ1Y3QgewoJTmFtZSAgICAgIHN0cmluZyAgYGpzb246Im5hbWUiYAoJQWdlICAgICAgIGludCAgICAgYGpzb246ImFnZSJgCglIZWlnaHQgICAgZmxvYXQ2NCBganNvbjoiaGVpZ2h0ImAKCUlzU3R1ZGVudCBib29sICAgIGBqc29uOiJpc19zdHVkZW50ImAKCUFkZHJlc3MgICBBZGRyZXNzIGBqc29uOiJhZGRyZXNzImAKfQoKdHlwZSBBZGRyZXNzIHN0cnVjdCB7CglDaXR5IHN0cmluZyBganNvbjoiY2l0eSJgCglaaXAgIGludCAgICBganNvbjoiemlwImAKfQoKZnVuYyBtYXBEYXRhVG9TdHJ1Y3QoZGF0YSBtYXBbc3RyaW5nXWludGVyZmFjZXt9LCB0YXJnZXQgaW50ZXJmYWNle30pIGVycm9yIHsKCXYgOj0gcmVmbGVjdC5WYWx1ZU9mKHRhcmdldCkuRWxlbSgpCglmb3Iga2V5LCB2YWwgOj0gcmFuZ2UgZGF0YSB7CgkJZmllbGQgOj0gdi5GaWVsZEJ5TmFtZShrZXkpCgkJaWYgIWZpZWxkLklzVmFsaWQoKSB7CgkJCWxvZy5QcmludGYoIkludmFsaWQga2V5IGluIGRhdGE6ICVzIiwga2V5KQoJCQljb250aW51ZQoJCX0KCQlpZiAhZmllbGQuQ2FuU2V0KCkgewoJCQlyZXR1cm4gZm10LkVycm9yZigiRmllbGQgJyVzJyBpcyBub3Qgc2V0dGFibGUiLCBrZXkpCgkJfQoKCQl0eXAgOj0gZmllbGQuVHlwZSgpCgoJCS8vIEhhbmRsaW5nIG5lc3RlZCBzdHJ1Y3RzIChlLmcuLCBBZGRyZXNzKQoJCWlmIHR5cC5LaW5kKCkgPT0gcmVmbGVjdC5TdHJ1Y3QgJiYgcmVmbGVjdC5WYWx1ZU9mKHZhbCkuS2luZCgpID09IHJlZmxlY3QuTWFwIHsKCQkJaWYgZXJyIDo9IG1hcERhdGFUb1N0cnVjdCh2YWwuKG1hcFtzdHJpbmddaW50ZXJmYWNle30pLCBmaWVsZC5BZGRyKCkuSW50ZXJmYWNlKCkpOyBlcnIgIT0gbmlsIHsKCQkJCXJldHVybiBlcnIKCQkJfQoJCQljb250aW51ZQoJCX0KCgkJc3dpdGNoIHYgOj0gdmFsLih0eXBlKSB7CgkJY2FzZSBzdHJpbmc6CgkJCXN3aXRjaCB0eXAuS2luZCgpIHsKCQkJY2FzZSByZWZsZWN0LkludDoKCQkJCWksIGVyciA6PSBzdHJjb252LkF0b2kodikKCQkJCWlmIGVyciAhPSBuaWwgewoJCQkJCXJldHVybiBmbXQuRXJyb3JmKCJFcnJvciBjb252ZXJ0aW5nIHRvIGludCBmb3IgZmllbGQgJyVzJzogJXYiLCBrZXksIGVycikKCQkJCX0KCQkJCWZpZWxkLlNldEludChpbnQ2NChpKSkKCQkJY2FzZSByZWZsZWN0LkZsb2F0NjQ6CgkJCQlmLCBlcnIgOj0gc3RyY29udi5QYXJzZUZsb2F0KHYsIDY0KQoJCQkJaWYgZXJyICE9IG5pbCB7CgkJCQkJcmV0dXJuIGZtdC5FcnJvcmYoIkVycm9yIGNvbnZlcnRpbmcgdG8gZmxvYXQ2NCBmb3IgZmllbGQgJyVzJzogJXYiLCBrZXksIGVycikKCQkJCX0KCQkJCWZpZWxkLlNldEZsb2F0KGYpCgkJCWNhc2UgcmVmbGVjdC5Cb29sOgoJCQkJYiwgZXJyIDo9IHN0cmNvbnYuUGFyc2VCb29sKHYpCgkJCQlpZiBlcnIgIT0gbmlsIHsKCQkJCQlyZXR1cm4gZm10LkVycm9yZigiRXJyb3IgY29udmVydGluZyB0byBib29sIGZvciBmaWVsZCAnJXMnOiAldiIsIGtleSwgZXJyKQoJCQkJfQoJCQkJZmllbGQuU2V0Qm9vbChiKQoJCQlkZWZhdWx0OgoJCQkJZmllbGQuU2V0U3RyaW5nKHYpCgkJCX0KCQljYXNlIGludDoKCQkJaWYgdHlwLktpbmQoKSA9PSByZWZsZWN0LkZsb2F0NjQgewoJCQkJZmllbGQuU2V0RmxvYXQoZmxvYXQ2NCh2KSkKCQkJfSBlbHNlIHsKCQkJCWZpZWxkLlNldEludChpbnQ2NCh2KSkKCQkJfQoJCWNhc2UgZmxvYXQ2NDoKCQkJaWYgdHlwLktpbmQoKSA9PSByZWZsZWN0LkludCB7CgkJCQlmaWVsZC5TZXRJbnQoaW50NjQodikpCgkJCX0gZWxzZSB7CgkJCQlmaWVsZC5TZXRGbG9hdCh2KQoJCQl9CgkJY2FzZSBib29sOgoJCQlmaWVsZC5TZXRCb29sKHYpCgkJZGVmYXVsdDoKCQkJcmV0dXJuIGZtdC5FcnJvcmYoIlVuc3VwcG9ydGVkIHR5cGUgZm9yIGZpZWxkICclcyc6ICVUIiwga2V5LCB2YWwpCgkJfQoJfQoJcmV0dXJuIG5pbAp9CgpmdW5jIG1haW4oKSB7CglpbnB1dERhdGEgOj0gbWFwW3N0cmluZ11pbnRlcmZhY2V7fXsKCQkibmFtZSI6ICAgICAgICJKZW5ueSBEb2UiLAoJCSJhZ2UiOiAgICAgICAgMjgsCgkJImhlaWdodCI6ICAgICAxLjY1LAoJCSJpc19zdHVkZW50IjogdHJ1ZSwKCQkiYWRkcmVzcyI6IG1hcFtzdHJpbmddaW50ZXJmYWNle317CgkJCSJjaXR5IjogIlNhbiBGcmFuY2lzY28iLAoJCQkiemlwIjogIDk0MTAyLAoJCX0sCgkJImdlbmRlciI6ICJmZW1hbGUiLCAvLyBVbnN1cHBvcnRlZCBmaWVsZAoJfQoKCXZhciBwZXJzb24gUGVyc29uCglpZiBlcnIgOj0gbWFwRGF0YVRvU3RydWN0KGlucHV0RGF0YSwgJnBlcnNvbik7IGVyciAhPSBuaWwgewoJCWxvZy5GYXRhbGYoIkVycm9yIG1hcHBpbmcgZGF0YTogJXYiLCBlcnIpCgl9CgoJZm10LlByaW50ZigiUGVyc29uIGFmdGVyIG1hcHBpbmc6ICUrdlxuIiwgcGVyc29uKQp9Cg==