Advertisement
Guest User

Untitled

a guest
Sep 26th, 2017
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.42 KB | None | 0 0
  1. package structmap
  2.  
  3. import (
  4. "fmt"
  5. "reflect"
  6. "strings"
  7. )
  8.  
  9. type Options struct {
  10. Strict bool
  11. NameMapper func(name string) string
  12. }
  13.  
  14. func applyDefaults(o *Options) *Options {
  15. if o == nil {
  16. o = &Options{}
  17. }
  18. if o.NameMapper == nil {
  19. o.NameMapper = normalizeName
  20. }
  21. return o
  22. }
  23.  
  24. func MapToStruct(m map[string]interface{}, s interface{}, o *Options) error {
  25. o = applyDefaults(o)
  26. val := reflect.ValueOf(s).Elem()
  27. fields := make(map[string]reflect.Value)
  28. fieldMap(val, fields, o)
  29. for name, value := range m {
  30. field, ok := fields[o.NameMapper(name)]
  31. if !ok {
  32. if o.Strict {
  33. return fmt.Errorf("missing field %s", name)
  34. }
  35. continue
  36. }
  37. if !field.CanSet() {
  38. return fmt.Errorf("cannot set %s field value", name)
  39. }
  40. val := reflect.ValueOf(value)
  41. if field.Type() != val.Type() {
  42. return fmt.Errorf("invalid type for field %s", name)
  43. }
  44. field.Set(val)
  45. }
  46. return nil
  47. }
  48.  
  49. func normalizeName(name string) string {
  50. name = strings.Replace(name, "_", "", -1)
  51. name = strings.Replace(name, "-", "", -1)
  52. return strings.ToLower(name)
  53. }
  54.  
  55. func fieldMap(s reflect.Value, m map[string]reflect.Value, o *Options) {
  56. var embedded []reflect.Value
  57. for i := 0; i < s.NumField(); i++ {
  58. typ := s.Type().Field(i)
  59. val := s.Field(i)
  60. if typ.Anonymous {
  61. embedded = append(embedded, val)
  62. }
  63. name := o.NameMapper(typ.Name)
  64. if _, ok := m[name]; !ok {
  65. m[name] = val
  66. }
  67. }
  68. for _, val := range embedded {
  69. fieldMap(val, m, o)
  70. }
  71. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement