fork download
  1. package main
  2.  
  3. import (
  4. "encoding/json"
  5. "fmt"
  6. "log"
  7. "reflect"
  8. "strconv"
  9. )
  10.  
  11. type User struct {
  12. ID int `json:"id"`
  13. Name string `json:"name"`
  14. Age float64 `json:"age"`
  15. IsActive bool `json:"isActive"`
  16. Address *Address `json:"address"`
  17. }
  18.  
  19. type Address struct {
  20. Street string `json:"street"`
  21. City string `json:"city"`
  22. }
  23.  
  24. func mapDataToStruct(data map[string]interface{}, target interface{}) error {
  25. v := reflect.ValueOf(target).Elem()
  26.  
  27. for key, val := range data {
  28. field := v.FieldByName(key)
  29. if !field.IsValid() {
  30. log.Printf("Warning: Invalid key in data: %s", key)
  31. continue
  32. }
  33.  
  34. if !field.CanSet() {
  35. return fmt.Errorf("field '%s' is not settable", key)
  36. }
  37.  
  38. rv := reflect.ValueOf(val)
  39.  
  40. // Check and initialize pointer fields
  41. if field.Kind() == reflect.Ptr {
  42. if field.IsNil() { // Safe alternative to IsZero
  43. field.Set(reflect.New(field.Type().Elem()))
  44. }
  45. field = field.Elem()
  46. }
  47.  
  48. switch field.Kind() {
  49. case reflect.Int:
  50. switch v := rv.Interface().(type) {
  51. case float64:
  52. field.SetInt(int64(v))
  53. case string:
  54. i, err := strconv.Atoi(v)
  55. if err != nil {
  56. return fmt.Errorf("error converting to int for field '%s': %v", key, err)
  57. }
  58. field.SetInt(int64(i))
  59. case int:
  60. field.SetInt(int64(v))
  61. default:
  62. return fmt.Errorf("invalid type for field '%s': expected int, got %T", key, val)
  63. }
  64. case reflect.Float64:
  65. switch v := rv.Interface().(type) {
  66. case float64:
  67. field.SetFloat(v)
  68. case string:
  69. f, err := strconv.ParseFloat(v, 64)
  70. if err != nil {
  71. return fmt.Errorf("error converting to float64 for field '%s': %v", key, err)
  72. }
  73. field.SetFloat(f)
  74. case int:
  75. field.SetFloat(float64(v))
  76. default:
  77. return fmt.Errorf("invalid type for field '%s': expected float64, got %T", key, val)
  78. }
  79. case reflect.String:
  80. if s, ok := rv.Interface().(string); ok {
  81. field.SetString(s)
  82. } else {
  83. return fmt.Errorf("invalid type for field '%s': expected string, got %T", key, val)
  84. }
  85. case reflect.Bool:
  86. switch v := rv.Interface().(type) {
  87. case bool:
  88. field.SetBool(v)
  89. case string:
  90. b, err := strconv.ParseBool(v)
  91. if err != nil {
  92. return fmt.Errorf("error converting to bool for field '%s': %v", key, err)
  93. }
  94. field.SetBool(b)
  95. default:
  96. return fmt.Errorf("invalid type for field '%s': expected bool, got %T", key, val)
  97. }
  98. case reflect.Struct:
  99. if nestedMap, ok := val.(map[string]interface{}); ok {
  100. if err := mapDataToStruct(nestedMap, field.Addr().Interface()); err != nil {
  101. return err
  102. }
  103. } else {
  104. return fmt.Errorf("invalid type for field '%s': expected map for nested struct, got %T", key, val)
  105. }
  106. default:
  107. return fmt.Errorf("unsupported field type for '%s': %s", key, field.Kind())
  108. }
  109. }
  110. return nil
  111. }
  112.  
  113. func main() {
  114. inputData := map[string]interface{}{
  115. "id": 1,
  116. "name": "Abak",
  117. "age": 25.6,
  118. "isActive": true,
  119. "address": map[string]interface{}{
  120. "street": "Bashundhara",
  121. "city": "Dhaka",
  122. },
  123. "gender": "male", // Unsupported field
  124. }
  125.  
  126. var user User
  127. if err := mapDataToStruct(inputData, &user); err != nil {
  128. log.Fatalf("Error mapping data: %v", err)
  129. }
  130.  
  131. jsonData, err := json.MarshalIndent(user, "", " ")
  132. if err != nil {
  133. log.Fatalf("Error marshaling JSON: %v", err)
  134. }
  135. fmt.Println("User data after mapping:")
  136. fmt.Println(string(jsonData))
  137. }
  138.  
Success #stdin #stdout #stderr 0.01s 5276KB
stdin
Standard input is empty
stdout
User data after mapping:
{
  "id": 0,
  "name": "",
  "age": 0,
  "isActive": false,
  "address": null
}
stderr
2024/12/17 06:52:41 Warning: Invalid key in data: id
2024/12/17 06:52:41 Warning: Invalid key in data: name
2024/12/17 06:52:41 Warning: Invalid key in data: age
2024/12/17 06:52:41 Warning: Invalid key in data: isActive
2024/12/17 06:52:41 Warning: Invalid key in data: address
2024/12/17 06:52:41 Warning: Invalid key in data: gender