fork download
  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "log"
  6. "reflect"
  7. "strconv"
  8. )
  9.  
  10. type Person struct {
  11. Name string `json:"name"`
  12. Age int `json:"age"`
  13. Height float64 `json:"height"`
  14. IsStudent bool `json:"is_student"`
  15. Address Address `json:"address"`
  16. }
  17.  
  18. type Address struct {
  19. City string `json:"city"`
  20. Zip int `json:"zip"`
  21. }
  22.  
  23. func mapDataToStruct(data map[string]interface{}, target interface{}) error {
  24. v := reflect.ValueOf(target).Elem()
  25. for key, val := range data {
  26. field := v.FieldByName(key)
  27. if !field.IsValid() {
  28. log.Printf("Invalid key in data: %s", key)
  29. continue
  30. }
  31. if !field.CanSet() {
  32. return fmt.Errorf("Field '%s' is not settable", key)
  33. }
  34.  
  35. typ := field.Type()
  36.  
  37. // Handling nested structs (e.g., Address)
  38. if typ.Kind() == reflect.Struct && reflect.ValueOf(val).Kind() == reflect.Map {
  39. if err := mapDataToStruct(val.(map[string]interface{}), field.Addr().Interface()); err != nil {
  40. return err
  41. }
  42. continue
  43. }
  44.  
  45. switch v := val.(type) {
  46. case string:
  47. switch typ.Kind() {
  48. case reflect.Int:
  49. i, err := strconv.Atoi(v)
  50. if err != nil {
  51. return fmt.Errorf("Error converting to int for field '%s': %v", key, err)
  52. }
  53. field.SetInt(int64(i))
  54. case reflect.Float64:
  55. f, err := strconv.ParseFloat(v, 64)
  56. if err != nil {
  57. return fmt.Errorf("Error converting to float64 for field '%s': %v", key, err)
  58. }
  59. field.SetFloat(f)
  60. case reflect.Bool:
  61. b, err := strconv.ParseBool(v)
  62. if err != nil {
  63. return fmt.Errorf("Error converting to bool for field '%s': %v", key, err)
  64. }
  65. field.SetBool(b)
  66. default:
  67. field.SetString(v)
  68. }
  69. case int:
  70. if typ.Kind() == reflect.Float64 {
  71. field.SetFloat(float64(v))
  72. } else {
  73. field.SetInt(int64(v))
  74. }
  75. case float64:
  76. if typ.Kind() == reflect.Int {
  77. field.SetInt(int64(v))
  78. } else {
  79. field.SetFloat(v)
  80. }
  81. case bool:
  82. field.SetBool(v)
  83. default:
  84. return fmt.Errorf("Unsupported type for field '%s': %T", key, val)
  85. }
  86. }
  87. return nil
  88. }
  89.  
  90. func main() {
  91. inputData := map[string]interface{}{
  92. "name": "Jenny Doe",
  93. "age": 28,
  94. "height": 1.65,
  95. "is_student": true,
  96. "address": map[string]interface{}{
  97. "city": "San Francisco",
  98. "zip": 94102,
  99. },
  100. "gender": "female", // Unsupported field
  101. }
  102.  
  103. var person Person
  104. if err := mapDataToStruct(inputData, &person); err != nil {
  105. log.Fatalf("Error mapping data: %v", err)
  106. }
  107.  
  108. fmt.Printf("Person after mapping: %+v\n", person)
  109. }
  110.  
Success #stdin #stdout #stderr 0.01s 5280KB
stdin
Standard input is empty
stdout
Person after mapping: {Name: Age:0 Height:0 IsStudent:false Address:{City: Zip:0}}
stderr
2024/12/17 06:46:59 Invalid key in data: address
2024/12/17 06:46:59 Invalid key in data: gender
2024/12/17 06:46:59 Invalid key in data: name
2024/12/17 06:46:59 Invalid key in data: age
2024/12/17 06:46:59 Invalid key in data: height
2024/12/17 06:46:59 Invalid key in data: is_student