Created
September 26, 2017 17:04
-
-
Save icholy/abdb02657ef656524ce2a006ca776b8f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package structmap | |
import ( | |
"fmt" | |
"reflect" | |
"strings" | |
) | |
type Options struct { | |
Strict bool | |
NameMapper func(name string) string | |
} | |
func applyDefaults(o *Options) *Options { | |
if o == nil { | |
o = &Options{} | |
} | |
if o.NameMapper == nil { | |
o.NameMapper = normalizeName | |
} | |
return o | |
} | |
func MapToStruct(m map[string]interface{}, s interface{}, o *Options) error { | |
o = applyDefaults(o) | |
val := reflect.ValueOf(s).Elem() | |
fields := make(map[string]reflect.Value) | |
fieldMap(val, fields, o) | |
for name, value := range m { | |
field, ok := fields[o.NameMapper(name)] | |
if !ok { | |
if o.Strict { | |
return fmt.Errorf("missing field %s", name) | |
} | |
continue | |
} | |
if !field.CanSet() { | |
return fmt.Errorf("cannot set %s field value", name) | |
} | |
val := reflect.ValueOf(value) | |
if field.Type() != val.Type() { | |
return fmt.Errorf("invalid type for field %s", name) | |
} | |
field.Set(val) | |
} | |
return nil | |
} | |
func normalizeName(name string) string { | |
name = strings.Replace(name, "_", "", -1) | |
name = strings.Replace(name, "-", "", -1) | |
return strings.ToLower(name) | |
} | |
func fieldMap(s reflect.Value, m map[string]reflect.Value, o *Options) { | |
var embedded []reflect.Value | |
for i := 0; i < s.NumField(); i++ { | |
typ := s.Type().Field(i) | |
val := s.Field(i) | |
if typ.Anonymous { | |
embedded = append(embedded, val) | |
} | |
name := o.NameMapper(typ.Name) | |
if _, ok := m[name]; !ok { | |
m[name] = val | |
} | |
} | |
for _, val := range embedded { | |
fieldMap(val, m, o) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment